diff options
author | Karel Zak | 2006-12-07 00:25:41 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:41 +0100 |
commit | eb63b9b8f4cecb34c2478282567862bc48ef256d (patch) | |
tree | 99243f8eecb44c2bb6a559982b99c680fcb649e7 /disk-utils | |
parent | Imported from util-linux-2.9v tarball. (diff) | |
download | kernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.tar.gz kernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.tar.xz kernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.zip |
Imported from util-linux-2.10f tarball.
Diffstat (limited to 'disk-utils')
-rw-r--r-- | disk-utils/Makefile | 36 | ||||
-rw-r--r-- | disk-utils/blockdev.c | 220 | ||||
-rw-r--r-- | disk-utils/fdformat.c | 20 | ||||
-rw-r--r-- | disk-utils/fsck.minix.c | 88 | ||||
-rw-r--r-- | disk-utils/mkfs.bfs.8 | 48 | ||||
-rw-r--r-- | disk-utils/mkfs.bfs.c | 284 | ||||
-rw-r--r-- | disk-utils/mkfs.c | 14 | ||||
-rw-r--r-- | disk-utils/mkfs.minix.8 | 44 | ||||
-rw-r--r-- | disk-utils/mkfs.minix.c | 26 | ||||
-rw-r--r-- | disk-utils/mkswap.8 | 31 | ||||
-rw-r--r-- | disk-utils/mkswap.c | 166 | ||||
-rw-r--r-- | disk-utils/raw.8 | 87 | ||||
-rw-r--r-- | disk-utils/raw.c | 217 | ||||
-rw-r--r-- | disk-utils/setfdprm.c | 23 |
14 files changed, 1138 insertions, 166 deletions
diff --git a/disk-utils/Makefile b/disk-utils/Makefile index b170e81ee..36f5e616f 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -1,49 +1,53 @@ # Makefile -- Makefile for util-linux Linux utilities # Created: Sat Dec 26 20:09:40 1992 -# Revised: Fri Oct 6 21:02:21 1995 by r.faith@ieee.org # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) -# + include ../make_include include ../MCONFIG # Where to put man pages? -MAN8= fdformat.8 mkswap.8 setfdprm.8 +MAN8= fdformat.8 mkfs.8 mkswap.8 # Where to put binaries? # See the "install" rule for the links. . . -SBIN= mkfs mkswap +SBIN= mkfs mkswap blockdev -USRBIN= fdformat setfdprm +USRBIN= fdformat ETC= fdprm ifneq "$(CPU)" "sparc" # fsck and mkfs will compile, but there is no kernel support on sparc -MAN8:=$(MAN8) fsck.minix.8 mkfs.8 mkfs.minix.8 -SBIN:=$(SBIN) fsck.minix mkfs.minix +MAN8:=$(MAN8) fsck.minix.8 mkfs.minix.8 mkfs.bfs.8 +SBIN:=$(SBIN) fsck.minix mkfs.minix mkfs.bfs endif -# Where to put datebase files? +ifneq "$(HAVE_FDUTILS)" "yes" +USRBIN:=$(USRBIN) setfdprm +MAN8:=$(MAN8) setfdprm.8 +endif + +# raw.c does not compile on 2.2.*. +# find out later where it does and add tests to config +ifeq "$(ADD_RAW)" "yes" +USRBIN:=$(USRBIN) raw +MAN8:=$(MAN8) raw.8 +endif all: $(SBIN) $(USRBIN) -fdformat: fdformat.o -fsck.minix: fsck.minix.o -fsck.minix.o: fsck.minix.c bitops.h -mkfs: mkfs.o -mkfs.minix: mkfs.minix.o -mkfs.minix.o: mkfs.minix.c bitops.h -mkswap: mkswap.o -setfdprm: setfdprm.o +fsck.minix.o mkfs.minix.o: bitops.h install: all $(INSTALLDIR) $(SBINDIR) $(USRBINDIR) $(ETCDIR) $(INSTALLBIN) $(SBIN) $(SBINDIR) $(INSTALLBIN) $(USRBIN) $(USRBINDIR) +ifneq "$(HAVE_FDUTILS)" "yes" $(INSTALLDAT) $(ETC) $(ETCDIR) +endif $(INSTALLDIR) $(MAN8DIR) $(INSTALLMAN) $(MAN8) $(MAN8DIR) diff --git a/disk-utils/blockdev.c b/disk-utils/blockdev.c new file mode 100644 index 000000000..7f1fd7bb8 --- /dev/null +++ b/disk-utils/blockdev.c @@ -0,0 +1,220 @@ +/* + * blockdev.c --- Do various simple block device ioctls from the command line + * aeb, 991028 + */ + +#include <stdio.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#include <linux/fs.h> +#include "nls.h" + +const char *progname; + +struct bdc { + char *name; + char *iocname; + long ioc; + int argtype; +#define ARGNONE 0 +#define ARGINTA 1 +#define ARGINTP 2 +#define ARGINTG 3 +#define ARGLINTG 4 + long argval; + char *argname; + char *help; +} bdcms[] = { +#ifdef BLKROSET + { "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") }, + { "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") }, +#endif +#ifdef BLKROGET + { "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") }, +#endif +#ifdef BLKSSZGET + { "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") }, +#endif +#ifdef BLKGETSIZE + { "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLINTG, -1, NULL, N_("get size") }, +#endif +#ifdef BLKRASET + { "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") }, +#endif +#ifdef BLKRAGET + { "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") }, +#endif +#ifdef BLKFLSBUF + { "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") }, +#endif +#ifdef BLKRRPART + { "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL, + N_("reread partition table") }, +#endif +}; + +#define SIZE(a) (sizeof(a)/sizeof((a)[0])) + +static void +usage(void) { + int i; + fprintf(stderr, _("Usage: %s [-V] [-v|-q] commands devices\n"), progname); + fprintf(stderr, _("Available commands:\n")); + for (i = 0; i < SIZE(bdcms); i++) { + fprintf(stderr, "\t%s", bdcms[i].name); + if (bdcms[i].argname) + fprintf(stderr, " %s", bdcms[i].argname); + if (bdcms[i].help) + fprintf(stderr, "\t(%s)", _(bdcms[i].help)); + fprintf(stderr, "\n"); + } + exit(1); +} + +int +find_cmd(char *s) { + int j; + + for (j = 0; j < SIZE(bdcms); j++) + if (!strcmp(s, bdcms[j].name)) + return j; + return -1; +} + +void do_commands(int fd, char **argv, int d); + +int +main(int argc, char **argv) { + int fd, d, j, k; + char *p; + + /* egcs-2.91.66 is buggy and says: + blockdev.c:93: warning: `d' might be used uninitialized */ + d = 0; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc < 2) + usage(); + + /* -V not together with commands */ + if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { + printf("%s from %s\n", progname, util_linux_version); + exit(0); + } + + /* do each of the commands on each of the devices */ + /* devices start after last command */ + for (d = 1; d < argc; d++) { + j = find_cmd(argv[d]); + if (j >= 0) { + if (bdcms[j].argtype == ARGINTA) + d++; + continue; + } + if (!strcmp(argv[d], "--")) { + d++; + break; + } + if (argv[d][0] != '-') + break; + } + + if (d >= argc) + usage(); + + for (k = d; k < argc; k++) { + fd = open(argv[k], O_RDONLY, 0); + if (fd < 0) { + perror(argv[k]); + exit(1); + } + do_commands(fd, argv, d); + } + return 0; +} + +void +do_commands(int fd, char **argv, int d) { + int res, i, j; + int iarg; + long larg; + int verbose = 0; + + for (i = 1; i < d; i++) { + if (!strcmp(argv[i], "-v")) { + verbose = 1; + continue; + } + if (!strcmp(argv[i], "-q")) { + verbose = 0; + continue; + } + + j = find_cmd(argv[i]); + if (j == -1) { + fprintf(stderr, _("%s: Unknown command: %s\n"), progname, argv[i]); + usage(); + } + + switch(bdcms[j].argtype) { + default: + case ARGNONE: + res = ioctl(fd, bdcms[j].ioc, 0); + break; + case ARGINTA: + if (i == d-1) { + fprintf(stderr, _("%s requires an argument\n"), + bdcms[j].name); + usage(); + } + iarg = atoi(argv[++i]); + res = ioctl(fd, bdcms[j].ioc, iarg); + break; + case ARGINTP: + case ARGINTG: + iarg = bdcms[j].argval; + res = ioctl(fd, bdcms[j].ioc, &iarg); + break; + case ARGLINTG: + larg = bdcms[j].argval; + res = ioctl(fd, bdcms[j].ioc, &larg); + break; + } + if (res == -1) { + perror(bdcms[j].iocname); + if (verbose) + printf("%s failed.\n", _(bdcms[j].help)); + exit(1); + } + switch(bdcms[j].argtype) { + case ARGINTG: + if (verbose) + printf("%s: %d\n", _(bdcms[j].help), iarg); + else + printf("%d\n", iarg); + break; + case ARGLINTG: + if (verbose) + printf("%s: %ld\n", _(bdcms[j].help), larg); + else + printf("%ld\n", larg); + break; + default: + if (verbose) + printf("%s succeeded.\n", _(bdcms[j].help)); + break; + } + } +} diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c index bb4f0a1f5..6c3ef5c91 100644 --- a/disk-utils/fdformat.c +++ b/disk-utils/fdformat.c @@ -101,22 +101,31 @@ static void usage(char *name) int main(int argc,char **argv) { int verify; - char *name; struct stat st; + char *progname, *p; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - name = argv[0]; + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), progname, util_linux_version); + exit(0); + } + verify = 1; if (argc > 1 && argv[1][0] == '-') { - if (argv[1][1] != 'n') usage(name); + if (argv[1][1] != 'n') usage(progname); verify = 0; argc--; argv++; } - if (argc != 2) usage(name); + if (argc != 2) usage(progname); if (stat(argv[1],&st) < 0) PERROR(argv[1]); if (!S_ISBLK(st.st_mode) || MAJOR(st.st_rdev) != FLOPPY_MAJOR) { fprintf(stderr,_("%s: not a floppy device\n"),argv[1]); @@ -127,7 +136,8 @@ int main(int argc,char **argv) if (ioctl(ctrl,FDGETPRM,(long) ¶m) < 0) PERROR(_("Could not determine current format type")); printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"), - param.head ? _("Double") : _("Single"),param.track,param.sect,param.size >> 1); + param.head ? _("Double") : _("Single"), + param.track, param.sect,param.size >> 1); format_disk(argv[1]); if (verify) verify_disk(argv[1]); return 0; diff --git a/disk-utils/fsck.minix.c b/disk-utils/fsck.minix.c index 416c178cb..99a8ca853 100644 --- a/disk-utils/fsck.minix.c +++ b/disk-utils/fsck.minix.c @@ -98,7 +98,6 @@ #include <linux/fs.h> #include <linux/minix_fs.h> -#include "../version.h" #include "nls.h" #ifdef MINIX2_SUPER_MAGIC2 @@ -125,7 +124,6 @@ #define BITS_PER_BLOCK (BLOCK_SIZE<<3) static char * program_name = "fsck.minix"; -static char * program_version = "1.2 - 11/11/96"; static char * device_name = NULL; static int IN; static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0, @@ -185,17 +183,25 @@ void recursive_check2(unsigned int ino); #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1) #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1) -void fatal_error(const char *, int) __attribute__ ((noreturn)); -void fatal_error(const char * fmt_string, int status) +void leave(int) __attribute__ ((noreturn)); +void leave(int status) { - fprintf(stderr,fmt_string,program_name,device_name); if (termios_set) tcsetattr(0, TCSANOW, &termios); exit(status); } -#define usage() fatal_error(_("Usage: %s [-larvsmf] /dev/name\n"),16) -#define die(str) fatal_error(_("%s: " str "\n"),8) +void usage(void) { + fprintf(stderr, + _("Usage: %s [-larvsmf] /dev/name\n"), + program_name); + leave(16); +} + +void die(const char *str) { + fprintf(stderr, "%s: %s\n", program_name, str); + leave(8); +} /* * This simply goes through the file-name data and prints out the @@ -381,7 +387,7 @@ void write_block(unsigned int nr, char * addr) return; } if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) - die("seek failed in write_block"); + die(_("seek failed in write_block")); if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { printf(_("Write error: bad block in file '")); print_current_name(); @@ -502,9 +508,9 @@ void write_super_block(void) Super.s_state &= ~MINIX_ERROR_FS; if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) - die("seek failed in write_super_block"); + die(_("seek failed in write_super_block")); if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) - die("unable to write super-block"); + die(_("unable to write super-block")); return; } @@ -514,11 +520,11 @@ void write_tables(void) write_super_block(); if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE)) - die("Unable to write inode map"); + die(_("Unable to write inode map")); if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE)) - die("Unable to write zone map"); + die(_("Unable to write zone map")); if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE)) - die("Unable to write inodes"); + die(_("Unable to write inodes")); } void get_dirsize (void) @@ -547,9 +553,9 @@ void get_dirsize (void) void read_superblock(void) { if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) - die("seek failed"); + die(_("seek failed")); if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE)) - die("unable to read super block"); + die(_("unable to read super block")); if (MAGIC == MINIX_SUPER_MAGIC) { namelen = 14; dirsize = 16; @@ -569,20 +575,20 @@ void read_superblock(void) version2 = 1; #endif } else - die("bad magic number in super-block"); + die(_("bad magic number in super-block")); if (ZONESIZE != 0 || BLOCK_SIZE != 1024) - die("Only 1k blocks/zones supported"); + die(_("Only 1k blocks/zones supported")); if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) - die("bad s_imap_blocks field in super-block"); + die(_("bad s_imap_blocks field in super-block")); if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) - die("bad s_zmap_blocks field in super-block"); + die(_("bad s_zmap_blocks field in super-block")); } void read_tables(void) { inode_map = malloc(IMAPS * BLOCK_SIZE); if (!inode_map) - die("Unable to allocate buffer for inode map"); + die(_("Unable to allocate buffer for inode map")); zone_map = malloc(ZMAPS * BLOCK_SIZE); if (!inode_map) die("Unable to allocate buffer for zone map"); @@ -590,19 +596,19 @@ void read_tables(void) memset(zone_map,0,sizeof(zone_map)); inode_buffer = malloc(INODE_BUFFER_SIZE); if (!inode_buffer) - die("Unable to allocate buffer for inodes"); + die(_("Unable to allocate buffer for inodes")); inode_count = malloc(INODES + 1); if (!inode_count) - die("Unable to allocate buffer for inode count"); + die(_("Unable to allocate buffer for inode count")); zone_count = malloc(ZONES); if (!zone_count) - die("Unable to allocate buffer for zone count"); + die(_("Unable to allocate buffer for zone count")); if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE)) - die("Unable to read inode map"); + die(_("Unable to read inode map")); if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE)) - die("Unable to read zone map"); + die(_("Unable to read zone map")); if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE)) - die("Unable to read inodes"); + die(_("Unable to read inodes")); if (NORM_FIRSTZONE != FIRSTZONE) { printf(_("Warning: Firstzone != Norm_firstzone\n")); errors_uncorrected = 1; @@ -723,7 +729,7 @@ void check_root(void) struct minix_inode * inode = Inode + ROOT_INO; if (!inode || !S_ISDIR(inode->i_mode)) - die("root inode isn't a directory"); + die(_("root inode isn't a directory")); } #ifdef HAVE_MINIX2 @@ -1065,7 +1071,7 @@ void recursive_check(unsigned int ino) dir = Inode + ino; if (!S_ISDIR(dir->i_mode)) - die("internal error"); + die(_("internal error")); if (dir->i_size < 2 * dirsize) { print_current_name(); printf(_(": bad directory: size<32")); @@ -1100,7 +1106,7 @@ int bad_zone(int i) char buffer[1024]; if (BLOCK_SIZE*i != lseek(IN, BLOCK_SIZE*i, SEEK_SET)) - die("seek failed in bad_zone"); + die(_("seek failed in bad_zone")); return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); } @@ -1234,19 +1240,27 @@ int main(int argc, char ** argv) struct termios tmp; int count; int retcode = 0; + char *p; + + program_name = (argc && *argv) ? argv[0] : "fsck.minix"; + if ((p = strrchr(program_name, '/')) != NULL) + program_name = p+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - - if (argc && *argv) - program_name = *argv; + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), program_name, util_linux_version); + exit(0); + } + if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad inode size"); + die(_("bad inode size")); #ifdef HAVE_MINIX2 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad v2 inode size"); + die(_("bad v2 inode size")); #endif while (argc-- > 1) { argv++; @@ -1272,11 +1286,11 @@ int main(int argc, char ** argv) check_mount(); /* trying to check a mounted filesystem? */ if (repair && !automatic) { if (!isatty(0) || !isatty(1)) - die("need terminal for interactive repairs"); + die(_("need terminal for interactive repairs")); } IN = open(device_name,repair?O_RDWR:O_RDONLY); if (IN < 0) - die("unable to open '%s'"); + die(_("unable to open '%s'")); for (count=0 ; count<3 ; count++) sync(); read_superblock(); @@ -1287,8 +1301,6 @@ int main(int argc, char ** argv) * flags and whether or not the -f switch was specified on the * command line. */ - printf("%s, %s / %s\n", program_name, program_version, - util_linux_version); if ( !(Super.s_state & MINIX_ERROR_FS) && (Super.s_state & MINIX_VALID_FS) && !force ) { diff --git a/disk-utils/mkfs.bfs.8 b/disk-utils/mkfs.bfs.8 new file mode 100644 index 000000000..4da40e206 --- /dev/null +++ b/disk-utils/mkfs.bfs.8 @@ -0,0 +1,48 @@ +.\" Copyright 1999 Andries E. Brouwer (aeb@cwi.nl) +.\" May be freely distributed. +.TH MKFS.BFS 8 "12 Sept 1999" "Util-linux 2.9x" "Linux System Administrator's Manual" +.SH NAME +mkfs.bfs \- make an SCO bfs filesystem +.SH SYNOPSIS +.BR "mkfs.bfs [ \-N" +nr-of-inodes +.B ] [ \-V +volume-name +.B ] [ \-F +fsname +.B ] +device +.B [ +size-in-blocks +.B ] +.SH DESCRIPTION +.B mkfs.bfs +creates an SCO bfs file-system on a block device +(usually a disk partition or a file accessed via the loop device). + +The +.I size-in-blocks +parameter is the desired size of the file system, in blocks. +If nothing is specified, the entire partition will be used. + +.SH OPTIONS +.TP +.B \-N +Specify the desired number of inodes (at most 512). +If nothing is specified some default number in the range 48-512 is picked +depending on the size of the partition. +.TP +.BI \-V " volume-label" +Specify the volume label. I have no idea if/where this is used. +.TP +.BI \-F " fsname" +Specify the fsname. I have no idea if/where this is used. +.TP +.B \-v +Be verbose. +.SH "EXIT CODES" +The exit code returned by +.B mkfs.bfs +is 0 when all went well, and 1 when something went wrong. +.SH "SEE ALSO" +.BR mkfs (8). diff --git a/disk-utils/mkfs.bfs.c b/disk-utils/mkfs.bfs.c new file mode 100644 index 000000000..93cf1e60a --- /dev/null +++ b/disk-utils/mkfs.bfs.c @@ -0,0 +1,284 @@ +/* + * mkfs.bfs - Create SCO BFS filesystem - aeb, 1999-09-07 + * + * Usage: mkfs.bfs [-N nr-of-inodes] [-V volume-name] [-F fsname] device + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <time.h> + +#include <linux/fs.h> /* for BLKGETSIZE */ + +#include "../defines.h" /* for util_linux_version */ + +#define BFS_ROOT_INO 2 +#define BFS_NAMELEN 14 +#define BFS_BLOCKSIZE 512 +#define BFS_SUPER_MAGIC 0x1badface + +/* superblock - 512 bytes */ +struct bfssb { + unsigned int s_magic; + unsigned int s_start; /* byte offset of start of data */ + unsigned int s_end; /* sizeof(slice)-1 */ + + /* for recovery during compaction */ + int s_from, s_to; /* src and dest block of current transfer */ + int s_backup_from, s_backup_to; + + /* labels - may well contain garbage */ + char s_fsname[6]; + char s_volume[6]; + char s_pad[472]; +}; + +/* inode - 64 bytes */ +struct bfsi { + unsigned short i_ino; + unsigned char i_pad1[2]; + unsigned long i_first_block; + unsigned long i_last_block; + unsigned long i_bytes_to_end; + unsigned long i_type; /* 1: file, 2: the unique dir */ + unsigned long i_mode; + unsigned long i_uid, i_gid; + unsigned long i_nlinks; + unsigned long i_atime, i_mtime, i_ctime; + unsigned char i_pad2[16]; +}; + +#define BFS_DIR_TYPE 2 + +/* directory entry - 16 bytes */ +struct bfsde { + unsigned short d_ino; + char d_name[BFS_NAMELEN]; +}; + + +static char *progname; + +static void +fatal(char *s, ...) { + va_list p; + + va_start(p, s); + fflush(stdout); + fprintf(stderr, "\n%s: ", progname); + vfprintf(stderr, s, p); + va_end(p); + fprintf(stderr, "\n"); + exit(1); +} + +static void +usage(void) { + fprintf(stderr, + "Usage: %s [-v] [-N nr-of-inodes] [-V volume-name]\n" + " [-F fsname] device [block-count]\n", + progname); + exit(1); +} + +int +main(int argc, char *argv[]) { + char *device, *volume, *fsname; + int inodes; + unsigned long total_blocks, ino_bytes, ino_blocks, data_blocks; + unsigned long user_specified_total_blocks = 0; + int verbose = 0; + int fd; + struct bfssb sb; + struct bfsi ri; + struct bfsde de; + struct stat statbuf; + time_t now; + int c, i, len; + char *p; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + if (argc < 2) + usage(); + + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf("%s from %s\n", progname, util_linux_version); + exit(0); + } + + volume = fsname = " "; /* is there a default? */ + inodes = 0; + + while (EOF != (c = getopt(argc, argv, "vF:N:V:cl:"))) { + switch (c) { + case 'N': + inodes = atol(optarg); + break; + + case 'V': + len = strlen(optarg); + if (len <= 0 || len > 6) + fatal("volume name too long"); + volume = strdup(optarg); + break; + + case 'F': + len = strlen(optarg); + if (len <= 0 || len > 6) + fatal("fsname name too long"); + fsname = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + + /* when called via mkfs we may get options c,l,v */ + case 'c': + case 'l': + break; + + default: + usage(); + } + } + + if (optind == argc) + usage(); + + device = argv[optind++]; + + if (stat(device, &statbuf) == -1) { + perror(device); + fatal("cannot stat device %s", device); + } + + if (!S_ISBLK(statbuf.st_mode)) + fatal("%s is not a block special device", device); + + fd = open(device, O_RDWR); + if (fd == -1) { + perror(device); + fatal("cannot open %s", device); + } + + if (optind == argc-1) + user_specified_total_blocks = atoi(argv[optind]); + else if (optind != argc) + usage(); + + if (ioctl(fd, BLKGETSIZE, &total_blocks) == -1) { + if (!user_specified_total_blocks) { + perror("BLKGETSIZE"); + fatal("cannot get size of %s", device); + } + total_blocks = user_specified_total_blocks; + } else if (user_specified_total_blocks) { + if (user_specified_total_blocks > total_blocks) + fatal("blocks argument too large, max is %d", + total_blocks); + total_blocks = user_specified_total_blocks; + } + + if (!inodes) { + /* pick some reasonable default */ + inodes = 8*(total_blocks/800); + if (inodes < 48) + inodes = 48; + if (inodes > 512) + inodes = 512; + } else { + /* believe the user */ + if (inodes > 512) + fatal("too many inodes - max is 512"); + } + + ino_bytes = inodes * sizeof(struct bfsi); + ino_blocks = (ino_bytes + BFS_BLOCKSIZE - 1) / BFS_BLOCKSIZE; + data_blocks = total_blocks - ino_blocks - 1; + + /* mimic the behaviour of SCO's mkfs - maybe this limit is needed */ + if (data_blocks < 32) + fatal("not enough space, need at least %d blocks", + ino_blocks + 33); + + memset(&sb, 0, sizeof(sb)); + sb.s_magic = BFS_SUPER_MAGIC; + sb.s_start = ino_bytes + sizeof(struct bfssb); + sb.s_end = total_blocks * BFS_BLOCKSIZE - 1; + sb.s_from = sb.s_to = sb.s_backup_from = sb.s_backup_to = -1; + memcpy(sb.s_fsname, fsname, 6); + memcpy(sb.s_volume, volume, 6); + + if (verbose) { + fprintf(stderr, "Device: %s\n", device); + fprintf(stderr, "Volume: <%-6s>\n", volume); + fprintf(stderr, "FSname: <%-6s>\n", fsname); + fprintf(stderr, "BlockSize: %d\n", BFS_BLOCKSIZE); + fprintf(stderr, "Inodes: %d (in %ld block%s)\n", + inodes, ino_blocks, (ino_blocks==1) ? "" : "s"); + fprintf(stderr, "Blocks: %ld\n", total_blocks); + fprintf(stderr, "Inode end: %d, Data end: %d\n", + sb.s_start-1, sb.s_end); + } + + if (write(fd, &sb, sizeof(sb)) != sizeof(sb)) + fatal("error writing superblock"); + + memset(&ri, 0, sizeof(ri)); + ri.i_ino = BFS_ROOT_INO; + ri.i_first_block = 1 + ino_blocks; + ri.i_last_block = ri.i_first_block + + (inodes * sizeof(de) - 1) / BFS_BLOCKSIZE; + ri.i_bytes_to_end = ri.i_first_block * BFS_BLOCKSIZE + + 2 * sizeof(struct bfsde) - 1; + ri.i_type = BFS_DIR_TYPE; + ri.i_mode = S_IFDIR | 0755; /* or just 0755 */ + ri.i_uid = 0; + ri.i_gid = 1; /* random */ + ri.i_nlinks = 2; + time(&now); + ri.i_atime = now; + ri.i_mtime = now; + ri.i_ctime = now; + + if (write(fd, &ri, sizeof(ri)) != sizeof(ri)) + fatal("error writing root inode"); + + memset(&ri, 0, sizeof(ri)); + for (i=1; i<inodes; i++) + if (write(fd, &ri, sizeof(ri)) != sizeof(ri)) + fatal("error writing inode"); + + if (lseek(fd, (1 + ino_blocks)*BFS_BLOCKSIZE, SEEK_SET) == -1) + fatal("seek error"); + + memset(&de, 0, sizeof(de)); + de.d_ino = BFS_ROOT_INO; + memcpy(de.d_name, ".", 1); + if (write(fd, &de, sizeof(de)) != sizeof(de)) + fatal("error writing . entry"); + + memcpy(de.d_name, "..", 2); + if (write(fd, &de, sizeof(de)) != sizeof(de)) + fatal("error writing .. entry"); + + if (close(fd) == -1) { + perror(device); + fatal("error closing %s", device); + } + + return 0; +} diff --git a/disk-utils/mkfs.c b/disk-utils/mkfs.c index 9ea27a504..5ca2704c5 100644 --- a/disk-utils/mkfs.c +++ b/disk-utils/mkfs.c @@ -24,7 +24,6 @@ #include <limits.h> #include "nls.h" -#include "../version.h" #define VERSION UTIL_LINUX_VERSION #ifndef DEFAULT_FSTYPE @@ -41,11 +40,22 @@ int main(int argc, char *argv[]) char *fstype = NULL; int i, more = 0, verbose = 0; char *oldpath, *newpath; + char *program_name, *p; + + program_name = argv[0]; + if ((p = strrchr(program_name, '/')) != NULL) + program_name = p+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), program_name, util_linux_version); + exit(0); + } + /* Check commandline options. */ opterr = 0; while ((more == 0) && ((i = getopt(argc, argv, "Vt:")) != EOF)) @@ -86,7 +96,7 @@ int main(int argc, char *argv[]) argv[--optind] = progname; if (verbose) { - puts(_("mkfs version " VERSION " (" __DATE__ ")")); + printf(_("mkfs version %s (%s)\n"), VERSION, __DATE__); i = optind; while (argv[i]) printf("%s ", argv[i++]); diff --git a/disk-utils/mkfs.minix.8 b/disk-utils/mkfs.minix.8 index 6a9c7931c..2325805a2 100644 --- a/disk-utils/mkfs.minix.8 +++ b/disk-utils/mkfs.minix.8 @@ -1,11 +1,10 @@ .\" Copyright 1992, 1993, 1994 Rickard E. Faith (faith@cs.unc.edu) .\" May be freely distributed. -.\" " for emacs hilit19 mode -.TH MKFS 8 "2 July 1996" "Util-linux 2.6" "Linux System Administrator's Manual" +.TH MKFS.MINIX 8 "2 July 1996" "Util-linux 2.6" "Linux System Administrator's Manual" .SH NAME -mkfs \- make a Linux MINIX filesystem +mkfs.minix \- make a Linux MINIX filesystem .SH SYNOPSIS -.BR "mkfs [ \-c | \-l filename ] [ \-n" +.BR "mkfs.minix [ \-c | \-l filename ] [ \-n" namelength .B ] [ \-i inodecount @@ -15,7 +14,7 @@ device size-in-blocks .B ] .SH DESCRIPTION -.B mkfs +.B mkfs.minix creates a Linux MINIX file-system on a device (usually a disk partition). The @@ -33,14 +32,11 @@ is usually of the following form: The .I size-in-blocks -parameter is the desired size of the file system, in blocks. This -information can be determined from the -.BR fdisk (8) -or -.BR cfdisk (8) -program. If omitted it will be determined automaticaly. Only block -counts strictly greater than 10 and strictly less than 65536 are -allowed. +parameter is the desired size of the file system, in blocks. +It is present only for backwards compatibility. +If omitted the size will be determined automatically. +Only block counts strictly greater than 10 and strictly less than +65536 are allowed. .SH OPTIONS .TP .B \-c @@ -50,7 +46,7 @@ are found, the count is printed. .BI \-n " namelength" Specify the maximum length of filenames. Currently, the only allowable values are 14 and 30. -.B 30 is the default. +The default is 30. .TP .BI \-i " inodecount" Specify the number of inodes for the filesystem. @@ -76,24 +72,4 @@ Usage or syntax error .SH "SEE ALSO" .BR mkfs (8), .BR fsck (8), -.BR mke2fs (8), -.BR e2fsck (8), .BR reboot (8) -.\" .SH AUTHORS -.\" Linus Torvalds (torvalds@cs.helsinki.fi). -.\" .br -.\" Error code values by Rik Faith (faith@cs.unc.edu) -.\" .br -.\" Inode request feature by Scott Heavner (sdh@po.cwru.edu) -.\" .br -.\" Support for the file system valid flag by Dr. Wettstein -.\" (greg%wind.uucp@plains.nodak.edu) -.\" .br -.\" Check to prevent mkfs of mounted filesystem and boot sector clearing -.\" by Daniel Quinlan (quinlan@yggdrasil.com) -.\" .br -.\" Minix v2 support by Andreas Schwab -.\" (schwab@issan.informatik.uni-dortmund.de), updated by Nicolai -.\" Langfeldt (janl@math.uio.no) -.\" .br -.\" Portability patch by Russell King. diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c index b05960b23..4887f05d1 100644 --- a/disk-utils/mkfs.minix.c +++ b/disk-utils/mkfs.minix.c @@ -76,7 +76,6 @@ #include <linux/minix_fs.h> #include "nls.h" -#include "../version.h" #ifdef MINIX2_SUPER_MAGIC2 #define HAVE_MINIX2 1 @@ -489,6 +488,7 @@ void setup_tables(void) ZONESIZE = 0; MAXSIZE = version2 ? 0x7fffffff : (7+512+512*512)*1024; ZONES = BLOCKS; + /* some magic nrs: 1 inode / 3 blocks */ if ( req_nr_inodes == 0 ) inodes = BLOCKS/3; @@ -507,9 +507,13 @@ void setup_tables(void) inodes = 65535; INODES = inodes; IMAPS = UPPER(INODES + 1,BITS_PER_BLOCK); - ZMAPS = 0; - while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK)) - ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK); + ZMAPS = UPPER(BLOCKS - (1+IMAPS+INODE_BLOCKS), BITS_PER_BLOCK+1); + /* The old code here + * ZMAPS = 0; + * while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK)) + * ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK); + * was no good, since it may loop. - aeb + */ FIRSTZONE = NORM_FIRSTZONE; inode_map = malloc(IMAPS * BLOCK_SIZE); zone_map = malloc(ZMAPS * BLOCK_SIZE); @@ -630,9 +634,23 @@ int main(int argc, char ** argv) char * tmp; struct stat statbuf; char * listfile = NULL; + char * p; if (argc && *argv) program_name = *argv; + if ((p = strrchr(program_name, '/')) != NULL) + program_name = p+1; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), program_name, util_linux_version); + exit(0); + } + if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) die(_("bad inode size")); #ifdef HAVE_MINIX2 diff --git a/disk-utils/mkswap.8 b/disk-utils/mkswap.8 index c16a89380..368ef3b5c 100644 --- a/disk-utils/mkswap.8 +++ b/disk-utils/mkswap.8 @@ -7,7 +7,7 @@ .SH NAME mkswap \- set up a Linux swap area .SH SYNOPSIS -.BI "mkswap [\-c] [\-v" N "] [\-f] " device " [" size "]" +.BI "mkswap [\-c] [\-v" N "] [\-f] [\-p " PSZ "] "device " [" size "]" .SH DESCRIPTION .B mkswap sets up a Linux swap area on a device or in a file. @@ -30,6 +30,8 @@ but can also be a file. The Linux kernel does not look at partition Id's, but many installation scripts will assume that partitions of hex type 82 (LINUX_SWAP) are meant to be swap partitions. +(Warning: Solaris also uses this type. Be careful not to kill +your Solaris partitions.) The .I size @@ -39,6 +41,18 @@ parameter is superfluous but retained for backwards compatibility. will use the entire partition or file if it is omitted. Specifying it is unwise - a typo may destroy your disk.) +The +.I PSZ +parameter specifies the page size to use. It is almost always +unnecessary (even unwise) to specify it, but certain old libc +versions lie about the page size, so it is possible that +.B mkswap +gets it wrong. The symptom is that a subsequent +.B swapon +fails because no swap signature is found. Typical values for +.I PSZ +are 4096 or 8192. + Linux knows about two styles of swap areas, old style and new style. The last 10 bytes of the first page of the swap area distinguishes them: old style has `SWAP_SPACE', new style has `SWAPSPACE2' as @@ -51,9 +65,9 @@ Also, the last 10 bytes hold the signature. So, if the page size is S, an old style swap area can describe at most 8*(S-10)-1 pages used for swapping. With S=4096 (as on i386), the useful area is at most 133890048 bytes -(almost 128 MB if you believe in 1 MB=2^20 bytes), and the rest is wasted. +(almost 128 MiB), and the rest is wasted. On an alpha and sparc64, with S=8192, the useful area is at most -535560992 bytes (almost 512 MB with the same proviso). +535560992 bytes (almost 512 MiB). The old setup wastes most of this bitmap page, because zero bits denote bad blocks or blocks past the end of the swap space, @@ -63,12 +77,12 @@ to use a swap space with hundreds of bad blocks. (I would not even use a swap space with 1 bad block.) In the new style swap area this is precisely what is done. 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. +It is roughly 2GiB on i386, PPC, m68k, ARM, 1GiB on sparc, 512MiB on mips, +128GiB on alpha and 3TiB on sparc64. Note that before 2.1.117 the kernel allocated one byte for each page, -while it now allocates two bytes, so that taking a swap area of 2 GB -in use might require 2 MB of kernel memory. +while it now allocates two bytes, so that taking a swap area of 2 GiB +in use might require 2 MiB of kernel memory. Presently, Linux allows 8 swap areas. The areas in use can be seen in the file @@ -114,6 +128,9 @@ Without this option will refuse to create a v0 swap on a device with a valid SPARC superblock, as that probably means one is going to erase the partition table. .TP +.BI "\-p " PSZ +Specify the page size to use. +.TP .B \-v0 Create an old style swap area. .TP diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index ef5f58c11..2803587b7 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -77,9 +77,20 @@ linux_version_code(void) { /* * 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(). + * and can only be found at run time -- we use getpagesize(), so that + * we do not need separate binaries e.g. for sun4, sun4c/d/m and sun4u. + * + * Even more unfortunately, getpagesize() does not always return + * the right information. For example, libc4 and libc5 do not use + * the system call but invent a value themselves + * (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC), and thus it may happen + * that e.g. on a sparc PAGE_SIZE=4096 and getpagesize() returns 8192. + * What to do? Let us allow the user to specify the pagesize explicitly. */ +static int user_pagesize = 0; +static int kernel_pagesize; /* obtained via getpagesize(); */ +static int defined_pagesize = 0; /* PAGE_SIZE, when that exists */ static int pagesize; static int *signature_page; @@ -94,12 +105,31 @@ struct swap_header_v1 { static void init_signature_page() { - pagesize = getpagesize(); - #ifdef PAGE_SIZE - if (pagesize != PAGE_SIZE) - fprintf(stderr, _("Assuming pages of size %d\n"), pagesize); + defined_pagesize = PAGE_SIZE; #endif + kernel_pagesize = getpagesize(); + pagesize = kernel_pagesize; + + if (user_pagesize) { + if ((user_pagesize & (user_pagesize-1)) || + user_pagesize < 1024) { + fprintf(stderr, _("Bad user-specified page size %d\n"), + user_pagesize); + exit(1); + } + pagesize = user_pagesize; + } + + if (user_pagesize && user_pagesize != kernel_pagesize && + user_pagesize != defined_pagesize) + fprintf(stderr, _("Using user-specified page size %d, " + "instead of the system values %d/%d\n"), + pagesize, kernel_pagesize, defined_pagesize); + else if (defined_pagesize && pagesize != defined_pagesize) + fprintf(stderr, _("Assuming pages of size %d (not %d)\n"), + pagesize, defined_pagesize); + signature_page = (int *) malloc(pagesize); memset(signature_page,0,pagesize); p = (struct swap_header_v1 *) signature_page; @@ -158,8 +188,8 @@ It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) -static void bit_set (unsigned int *addr, unsigned int nr) -{ +static void +bit_set (unsigned int *addr, unsigned int nr) { unsigned int r, m; addr += nr / (8 * sizeof(int)); @@ -168,8 +198,8 @@ static void bit_set (unsigned int *addr, unsigned int nr) *addr = r | m; } -static int bit_test_and_clear (unsigned int *addr, unsigned int nr) -{ +static int +bit_test_and_clear (unsigned int *addr, unsigned int nr) { unsigned int r, m; addr += nr / (8 * sizeof(int)); @@ -179,14 +209,19 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr) return (r & m) != 0; } -void fatal_error(const char * fmt_string) -{ - fprintf(stderr,fmt_string,program_name,device_name); +void +usage(void) { + fprintf(stderr, + _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n"), + program_name); exit(1); } -#define usage() fatal_error(_("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n")) -#define die(str) fatal_error(_("%s: " str "\n")) +void +die(const char *str) { + fprintf(stderr, "%s: %s\n", program_name, str); + exit(1); +} void page_ok(int page) { @@ -200,7 +235,7 @@ page_bad(int page) { bit_test_and_clear(signature_page, page); else { if (badpages == MAX_BADPAGES) - die("too many bad pages"); + die(_("too many bad pages")); p->badpages[badpages] = page; } badpages++; @@ -214,7 +249,7 @@ check_blocks(void) { buffer = malloc(pagesize); if (!buffer) - die("Out of memory"); + die(_("Out of memory")); current_page = 0; while (current_page < PAGES) { if (!check) { @@ -223,7 +258,7 @@ check_blocks(void) { } if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != current_page*pagesize) - die("seek failed in check_blocks"); + die(_("seek failed in check_blocks")); if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { page_bad(current_page++); continue; @@ -236,8 +271,8 @@ check_blocks(void) { printf(_("%d bad pages\n"), badpages); } -static long valid_offset (int fd, int offset) -{ +static long +valid_offset (int fd, int offset) { char ch; if (lseek (fd, offset, 0) < 0) @@ -248,8 +283,7 @@ static long valid_offset (int fd, int offset) } static int -find_size (int fd) -{ +find_size (int fd) { unsigned int high, low; low = 0; @@ -269,8 +303,7 @@ find_size (int fd) /* return size in pages, to avoid integer overflow */ static long -get_size(const char *file) -{ +get_size(const char *file) { int fd; long size; @@ -289,58 +322,85 @@ get_size(const char *file) return size; } -int main(int argc, char ** argv) -{ - char * tmp; +int +isnzdigit(char c) { + return (c >= '1' && c <= '9'); +} + +int +main(int argc, char ** argv) { struct stat statbuf; - int sz; + int i, sz; int maxpages; int goodpages; int offset; int force = 0; + char *block_count = 0; + char *pp; + + program_name = (argc && *argv) ? argv[0] : "fsck.minix"; + if ((pp = strrchr(program_name, '/')) != NULL) + program_name = pp+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - - - if (argc && *argv) - program_name = *argv; - init_signature_page(); /* get pagesize */ + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), program_name, util_linux_version); + exit(0); + } - 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(); - } else - device_name = argv[0]; - } else { - switch (argv[0][1]) { + for (i=1; i<argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { case 'c': check=1; break; case 'f': force=1; break; + case 'p': + pp = argv[i]+2; + if (!*pp && i+1 < argc) + pp = argv[++i]; + if (isnzdigit(*pp)) + user_pagesize=atoi(pp); + else + usage(); + break; case 'v': - version=atoi(argv[0]+2); + version = atoi(argv[0]+2); break; default: usage(); } - } + } else if (!device_name) { + device_name = argv[i]; + } else if (!block_count) { + block_count = argv[i]; + } else + usage(); } + + init_signature_page(); /* get pagesize */ + if (!device_name) { fprintf(stderr, _("%s: error: Nowhere to set up swap on?\n"), program_name); usage(); } + if (block_count) { + /* this silly user specified the number of blocks + explicitly */ + char *tmp; + int blocks_per_page = pagesize/1024; + PAGES = strtol(block_count,&tmp,0)/blocks_per_page; + if (*tmp) + usage(); + } sz = get_size(device_name); if (!PAGES) { PAGES = sz; @@ -401,7 +461,7 @@ int main(int argc, char ** argv) if (!S_ISBLK(statbuf.st_mode)) check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) - die("Will not try to make swapdevice on '%s'"); + die(_("Will not try to make swapdevice on '%s'")); #ifdef __sparc__ if (!force && version == 0) { @@ -410,7 +470,7 @@ int main(int argc, char ** argv) unsigned short *q, sum; if (read(DEV, buffer, 512) != 512) - die("fatal: first page unreadable"); + die(_("fatal: first page unreadable")); if (buffer[508] == 0xDA && buffer[509] == 0xBE) { q = (unsigned short *)(buffer + 510); for (sum = 0; q >= (unsigned short *) buffer;) @@ -431,7 +491,7 @@ the -f option to force it.\n"), if (version == 0 || check) check_blocks(); if (version == 0 && !bit_test_and_clear(signature_page,0)) - die("fatal: first page unreadable"); + die(_("fatal: first page unreadable")); if (version == 1) { p->version = version; p->last_page = PAGES-1; @@ -440,23 +500,23 @@ the -f option to force it.\n"), goodpages = PAGES - badpages - 1; if (goodpages <= 0) - die("Unable to set up swap-space: unreadable"); + die(_("Unable to set up swap-space: unreadable")); 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"); + die(_("unable to rewind swap-device")); if (write(DEV,(char*)signature_page+offset, pagesize-offset) != pagesize-offset) - die("unable to write signature page"); + die(_("unable to write signature page")); /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) */ if (fsync(DEV)) - die("fsync failed"); + die(_("fsync failed")); return 0; } diff --git a/disk-utils/raw.8 b/disk-utils/raw.8 new file mode 100644 index 000000000..cb8021668 --- /dev/null +++ b/disk-utils/raw.8 @@ -0,0 +1,87 @@ +.\" -*- nroff -*- +.TH RAW 8 "Aug 1999" "Version 0.1" +.SH NAME +raw \- bind a Linux raw character device +.SH SYNOPSIS +.B raw +.I /dev/raw<N> <major> <minor> +.PP +.B raw +.I /dev/raw<N> /dev/<blockdev> +.PP +.B raw +.B \-q +.I /dev/raw<N> +.PP +.B raw +.B \-qa +.SH DESCRIPTION +.B raw +is used to bind a Linux raw character device to a block device. Any +block device may be used: at the time of binding, the device driver does +not even have to be accessible (it may be loaded on demand as a kernel +module later). +.PP +.B raw +is used in two modes: it either sets raw device bindings, or it queries +existing bindings. When setting a raw device, +.I /dev/raw<N> +is the device name of an existing raw device node in the filesystem. +The block device to which it is to be bound can be specified either in +terms of its +.I major +and +.I minor +device numbers, or as a path name +.I /dev/<blockdev> +to an existing block device file. +.PP +The bindings already in existence can be queried with the +.I \-q +option, with is used either with a raw device filename to query that one +device, or with the +.I \-a +option to query all bound raw devices. +.PP +Once bound to a block device, a raw device can be opened, read and +written, just like the block device it is bound to. However, the raw +device does not behave exactly like the block device. In particular, +access to the raw device bypasses the kernel's block buffer cache +entirely: all I/O is done directly to and from the address space of the +process performing the I/O. If the underlying block device driver can +support DMA, then no data copying at all is required to complete the +I/O. +.PP +Because raw I/O involves direct hardware access to a process's memory, a +few extra restrictions must be observed. All I/Os must be correctly +aligned in memory and on disk: they must start at a sector offset on +disk, they must be an exact number of sectors long, and the data buffer +in virtual memory must also be aligned to a multiple of the sector +size. The sector size is 512 bytes for most devices. +.SH OPTIONS +.TP +.B -q +Set query mode. +.B raw +will query an existing binding instead of setting a new one. +.TP +.B -a +With +.B -q +, specifies that all bound raw devices should be queried. +.TP +.B -h +provides a usage summary. +.SH BUGS +The Linux +.B dd +(1) command does not currently align its buffers correctly, and so +cannot be used on raw devices. +.PP +Raw I/O devices do not maintain cache coherency with the Linux block +device buffer cache. If you use raw I/O to overwrite data already in +the buffer cache, the buffer cache will no longer correspond to the +contents of the actual storage device underneath. This is deliberate, +but is regarded either a bug or a feature depending on who you ask! +.SH AUTHOR +Stephen Tweedie (sct@redhat.com) diff --git a/disk-utils/raw.c b/disk-utils/raw.c new file mode 100644 index 000000000..5fb95348a --- /dev/null +++ b/disk-utils/raw.c @@ -0,0 +1,217 @@ +/* + * raw.c: User mode tool to bind and query raw character devices. + * + * Stephen Tweedie, 1999 + * + * This file may be redistributed under the terms of the GNU General + * Public License, version 2. + * + * Copyright Red Hat Software, 1999 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/sysmacros.h> +#include <sys/raw.h> + + + +char * progname; +int do_query = 0; +int do_query_all = 0; + +int master_fd; +int raw_minor; + +void open_raw_ctl(void); +int query(int minor, int quiet); +int bind (int minor, int block_major, int block_minor); + + +static void usage(int err) +{ + fprintf(stderr, + "Usage:\n" + " %s /dev/rawN <major> <minor>\n" + " %s /dev/rawN /dev/<blockdev>\n" + " %s -q /dev/rawN\n" + " %s -qa\n", + progname, progname, progname, progname); + exit(err); +} + + +int main(int argc, char *argv[]) +{ + char c; + char * raw_name; + char * block_name; + int err; + int block_major, block_minor; + int i; + + struct stat statbuf; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "ahq")) != EOF) { + switch (c) { + case 'a': + do_query_all = 1; + break; + case 'h': + usage(0); + case 'q': + do_query = 1; + break; + default: + usage(1); + } + } + + /* + * Check for, and open, the master raw device, /dev/raw + */ + + open_raw_ctl(); + + if (do_query_all) { + if (optind < argc) + usage(1); + for (i=1; i<255; i++) + query(i, 1); + exit(0); + } + + /* + * It's a bind or a single query. Either way we need a raw device. + */ + + if (optind >= argc) + usage(1); + raw_name = argv[optind++]; + + err = stat(raw_name, &statbuf); + if (err) { + fprintf (stderr, "Cannot locate raw device '%s' (%s)\n", + raw_name, strerror(errno)); + exit(2); + } + + if (!S_ISCHR(statbuf.st_mode)) { + fprintf (stderr, "raw device '%s' is not a character dev\n", + raw_name); + exit(2); + } + if (major(statbuf.st_rdev) != RAW_MAJOR) { + fprintf (stderr, "Device '%s' is not a raw dev\n", + raw_name); + exit(2); + } + + raw_minor = minor(statbuf.st_rdev); + + if (do_query) + return query(raw_minor, 0); + + /* + * It's not a query, so we still have some parsing to do. Have + * we been given a block device filename or a major/minor pair? + */ + + switch (argc - optind) { + case 1: + block_name = argv[optind]; + err = stat(block_name, &statbuf); + if (err) { + fprintf (stderr, + "Cannot locate block device '%s' (%s)\n", + block_name, strerror(errno)); + exit(2); + } + + if (!S_ISBLK(statbuf.st_mode)) { + fprintf (stderr, "Device '%s' is not a block dev\n", + block_name); + exit(2); + } + + block_major = major(statbuf.st_rdev); + block_minor = minor(statbuf.st_rdev); + break; + + case 2: + block_major = strtol(argv[optind], 0, 0); + block_minor = strtol(argv[optind+1], 0, 0); + break; + + default: + usage(1); + } + + return bind(raw_minor, block_major, block_minor); + return 0; + +} + + +void open_raw_ctl(void) +{ + master_fd = open("/dev/raw", O_RDWR, 0); + if (master_fd < 0) { + fprintf (stderr, + "Cannot open master raw device '/dev/raw' (%s)\n", + strerror(errno)); + exit(2); + } +} + +int query(int minor, int quiet) +{ + struct raw_config_request rq; + int err; + + rq.raw_minor = minor; + err = ioctl(master_fd, RAW_GETBIND, &rq); + if (err < 0) { + if (quiet && errno == ENODEV) + return 3; + fprintf (stderr, + "Error querying raw device (%s)\n", + strerror(errno)); + exit(3); + } + if (quiet && !rq.block_major && !rq.block_minor) + return 0; + printf ("/dev/raw%d: bound to major %d, minor %d\n", + minor, (int) rq.block_major, (int) rq.block_minor); + return 0; +} + +int bind(int minor, int block_major, int block_minor) +{ + struct raw_config_request rq; + int err; + + rq.raw_minor = minor; + rq.block_major = block_major; + rq.block_minor = block_minor; + err = ioctl(master_fd, RAW_SETBIND, &rq); + if (err < 0) { + fprintf (stderr, + "Error setting raw device (%s)\n", + strerror(errno)); + exit(3); + } + printf ("/dev/raw%d: bound to major %d, minor %d\n", + raw_minor, (int) rq.block_major, (int) rq.block_minor); + return 0; +} + diff --git a/disk-utils/setfdprm.c b/disk-utils/setfdprm.c index 7c2b0dc36..73b3b7174 100644 --- a/disk-utils/setfdprm.c +++ b/disk-utils/setfdprm.c @@ -109,18 +109,27 @@ gap rate spec1 fmt_gap\n"),name); } int -main(int argc,char **argv) +main(int argc, char **argv) { int fd; unsigned int cmd; - char *name; + char *progname, *p; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - name = argv[0]; - if (argc < 3) usage(name); + if (argc == 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), progname, util_linux_version); + exit(0); + } + + if (argc < 3) usage(progname); cmd = FDSETPRM; if (*argv[1] == '-') { switch (argv[1][1]) { @@ -142,7 +151,7 @@ main(int argc,char **argv) break; #endif default: - usage(name); + usage(progname); } argc--; argv++; @@ -152,11 +161,11 @@ main(int argc,char **argv) exit(1); } if (cmd != FDSETPRM && cmd != FDDEFPRM) { - if (argc != 2) usage(name); + if (argc != 2) usage(progname); cmd_without_param(cmd,fd); } if (argc != 11 && argc != 3) - usage(name); + usage(progname); else if (argc == 11) set_params(cmd,fd,&argv[2]); else |