From 5c36a0eb7cdb0360f9afd5d747c321f423b35984 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 7 Dec 2006 00:25:37 +0100 Subject: [PATCH] Imported from util-linux-2.9i tarball. --- ANNOUNCE | 21 +- README => HISTORY | 132 +- INSTALL | 57 + LSM | 13 +- MAINTAINERS | 23 +- MCONFIG | 57 +- Makefile | 13 +- attic/pidof.c | 95 + {text-utils => attic}/strings.1 | 0 {text-utils => attic}/strings.c | 0 bsd/Makefile | 17 - bsd/getopt.3 | 210 -- bsd/getopt.c | 116 - disk-utils/Makefile | 47 - disk-utils/cfdisk.8.bak | 407 ---- disk-utils/cfdisk.c.bak | 2066 ----------------- disk-utils/cfdisk.c.orig | 2066 ----------------- disk-utils/fdformat.c | 12 +- disk-utils/fdprm | 2 + disk-utils/frag.8 | 47 - disk-utils/frag.c | 311 --- disk-utils/fsck.minix.c | 28 +- disk-utils/mkfs.8 | 9 +- disk-utils/mkfs.minix.c | 4 +- disk-utils/mkswap.8 | 163 +- disk-utils/mkswap.c | 271 ++- disk-utils/setfdprm.c | 3 +- example.files/filesystems | 19 + example.files/issue0 | 1 + example.files/syslog.conf | 12 - example.files/syslog.conf.alt | 22 - fdisk/Makefile | 68 + {disk-utils => fdisk}/README.cfdisk | 0 {disk-utils => fdisk}/README.fdisk | 4 + {disk-utils => fdisk}/cfdisk.8 | 5 +- {disk-utils => fdisk}/cfdisk.c | 232 +- {disk-utils => fdisk}/fdisk.8 | 28 +- {disk-utils => fdisk}/fdisk.c | 674 +++--- {disk-utils => fdisk}/fdisk.h | 27 +- fdisk/fdiskaixlabel.c | 64 + fdisk/fdiskaixlabel.h | 34 + .../fdisklabel.c => fdisk/fdiskbsdlabel.c | 40 +- .../fdisklabel.h => fdisk/fdiskbsdlabel.h | 2 +- fdisk/fdisksgilabel.c | 888 +++++++ fdisk/fdisksgilabel.h | 133 ++ {disk-utils => fdisk}/fdisksunlabel.c | 269 ++- {disk-utils => fdisk}/fdisksunlabel.h | 3 +- {disk-utils => fdisk}/llseek.c | 0 {disk-utils => fdisk}/sfdisk.8 | 11 +- {disk-utils => fdisk}/sfdisk.c | 35 +- {disk-utils => fdisk}/sfdisk.examples | 0 games/Makefile | 2 +- {getopt => getopt-1.0.3a}/COPYING | 0 {getopt => getopt-1.0.3a}/Changelog | 6 + getopt-1.0.3a/Makefile | 52 + {getopt => getopt-1.0.3a}/README | 6 +- {getopt => getopt-1.0.3a}/TODO | 2 + {getopt => getopt-1.0.3a}/getopt.1 | 0 {getopt => getopt-1.0.3a}/getopt.c | 4 +- {getopt => getopt-1.0.3a}/gnu/getopt.c | 0 {getopt => getopt-1.0.3a}/gnu/getopt.h | 0 {getopt => getopt-1.0.3a}/gnu/getopt1.c | 0 {getopt => getopt-1.0.3a}/parse.bash | 0 {getopt => getopt-1.0.3a}/parse.tcsh | 19 +- {getopt => getopt-1.0.3a}/test.bash | 0 {getopt => getopt-1.0.3a}/test.tcsh | 0 getopt/Makefile | 56 - lib/Makefile | 17 + {bsd => lib}/err.c | 0 {bsd => lib}/err.h | 0 lib/linux_reboot.h | 30 + lib/my_reboot.c | 40 + {bsd => lib}/pathnames.h | 5 +- lib/setproctitle.c | 117 + lib/setproctitle.h | 7 + login-utils/Makefile | 51 +- login-utils/agetty.c | 8 +- login-utils/checktty.c | 24 +- login-utils/chfn.c | 17 +- login-utils/chsh.1 | 4 +- login-utils/chsh.c | 5 - login-utils/last.1.orig | 49 - login-utils/last.c | 26 +- login-utils/last.c.orig | 381 --- login-utils/login.1 | 6 +- login-utils/login.c | 141 +- login-utils/passwd.1 | 9 +- login-utils/passwd.c | 19 +- login-utils/shutdown.8 | 32 +- login-utils/shutdown.c | 239 +- login-utils/simpleinit.c | 18 +- login-utils/vipw.c | 5 +- misc-utils/Makefile | 13 +- misc-utils/cal.1 | 4 +- misc-utils/cal.c | 51 +- misc-utils/chkdupexe.pl | 8 +- misc-utils/ddate.1 | 12 +- misc-utils/ddate.c | 14 +- misc-utils/hostname.c.orig | 187 -- misc-utils/kill.c | 130 +- misc-utils/look.c | 163 +- misc-utils/mcookie.1 | 9 +- misc-utils/mcookie.c | 7 +- misc-utils/procs.c | 8 +- misc-utils/script.c | 28 +- misc-utils/setterm.c | 6 +- misc-utils/whereis.c | 2 + misc-utils/write.c | 19 +- mkminix-0.1/README | 47 + mkminix-0.1/linux/minix_fs.h | 135 ++ mkminix-0.1/mkmin-dj.h | 43 + mkminix-0.1/mkminix.diff | 46 + mount/Makefile | 45 +- mount/Makefile.standalone | 50 +- mount/fstab.5 | 2 +- mount/fstab.c | 305 ++- mount/fstab.h | 5 +- mount/getusername.c | 14 + mount/getusername.h | 1 + mount/linux_fs.h | 21 +- mount/losetup.c | 4 +- mount/mk_loop_h | 7 +- mount/mntent.c | 214 ++ mount/mntent.h | 16 + mount/mount.8 | 84 +- mount/mount.c | 534 ++--- mount/mount_by_label.c | 143 ++ mount/mount_by_label.h | 2 + mount/mount_constants.h | 20 + mount/mount_guess_fstype.c | 252 ++ mount/mount_guess_fstype.h | 15 + mount/nfsmount.c | 24 +- mount/nfsmount_xdr.c | 49 +- mount/sundries.c | 12 +- mount/swap.configure | 22 +- mount/swap_constants.h | 15 + mount/swapon.8 | 14 +- mount/swapon.c | 30 +- mount/umount.c | 145 +- mount/version.c | 3 +- sys-utils/Makefile | 16 +- sys-utils/ctrlaltdel.c | 10 +- sys-utils/hwclock.8 | 130 +- sys-utils/hwclock.c | 362 +-- sys-utils/ipcrm.c | 15 + sys-utils/ipcs.c | 30 +- sys-utils/kbdrate.8 | 7 + sys-utils/kbdrate.c | 15 +- sys-utils/lpcntl.8 | 30 - sys-utils/lpcntl.c | 54 - sys-utils/{sln.1 => sln.8} | 11 +- text-utils/Makefile | 19 +- text-utils/colcrt.c | 7 +- text-utils/colrm.c | 5 +- text-utils/column.c | 1 - text-utils/more.c | 129 +- text-utils/ul.c | 90 +- uio.h-diff | 20 - util-linux-2.1.Announce | 48 - util-linux-2.1.bin.Notes | 549 ----- util-linux-2.1.lsm | 23 - version.h | 5 +- 162 files changed, 5993 insertions(+), 8721 deletions(-) rename README => HISTORY (86%) create mode 100644 INSTALL create mode 100644 attic/pidof.c rename {text-utils => attic}/strings.1 (100%) rename {text-utils => attic}/strings.c (100%) delete mode 100644 bsd/Makefile delete mode 100644 bsd/getopt.3 delete mode 100644 bsd/getopt.c delete mode 100644 disk-utils/cfdisk.8.bak delete mode 100644 disk-utils/cfdisk.c.bak delete mode 100644 disk-utils/cfdisk.c.orig delete mode 100644 disk-utils/frag.8 delete mode 100644 disk-utils/frag.c create mode 100644 example.files/filesystems create mode 100644 example.files/issue0 delete mode 100644 example.files/syslog.conf delete mode 100644 example.files/syslog.conf.alt create mode 100644 fdisk/Makefile rename {disk-utils => fdisk}/README.cfdisk (100%) rename {disk-utils => fdisk}/README.fdisk (99%) rename {disk-utils => fdisk}/cfdisk.8 (98%) rename {disk-utils => fdisk}/cfdisk.c (92%) rename {disk-utils => fdisk}/fdisk.8 (89%) rename {disk-utils => fdisk}/fdisk.c (78%) rename {disk-utils => fdisk}/fdisk.h (73%) create mode 100644 fdisk/fdiskaixlabel.c create mode 100644 fdisk/fdiskaixlabel.h rename disk-utils/fdisklabel.c => fdisk/fdiskbsdlabel.c (96%) rename disk-utils/fdisklabel.h => fdisk/fdiskbsdlabel.h (99%) create mode 100644 fdisk/fdisksgilabel.c create mode 100644 fdisk/fdisksgilabel.h rename {disk-utils => fdisk}/fdisksunlabel.c (73%) rename {disk-utils => fdisk}/fdisksunlabel.h (97%) rename {disk-utils => fdisk}/llseek.c (100%) rename {disk-utils => fdisk}/sfdisk.8 (97%) rename {disk-utils => fdisk}/sfdisk.c (98%) rename {disk-utils => fdisk}/sfdisk.examples (100%) rename {getopt => getopt-1.0.3a}/COPYING (100%) rename {getopt => getopt-1.0.3a}/Changelog (53%) create mode 100644 getopt-1.0.3a/Makefile rename {getopt => getopt-1.0.3a}/README (93%) rename {getopt => getopt-1.0.3a}/TODO (83%) rename {getopt => getopt-1.0.3a}/getopt.1 (100%) rename {getopt => getopt-1.0.3a}/getopt.c (99%) rename {getopt => getopt-1.0.3a}/gnu/getopt.c (100%) rename {getopt => getopt-1.0.3a}/gnu/getopt.h (100%) rename {getopt => getopt-1.0.3a}/gnu/getopt1.c (100%) rename {getopt => getopt-1.0.3a}/parse.bash (100%) rename {getopt => getopt-1.0.3a}/parse.tcsh (83%) rename {getopt => getopt-1.0.3a}/test.bash (100%) rename {getopt => getopt-1.0.3a}/test.tcsh (100%) delete mode 100644 getopt/Makefile create mode 100644 lib/Makefile rename {bsd => lib}/err.c (100%) rename {bsd => lib}/err.h (100%) create mode 100644 lib/linux_reboot.h create mode 100644 lib/my_reboot.c rename {bsd => lib}/pathnames.h (95%) create mode 100644 lib/setproctitle.c create mode 100644 lib/setproctitle.h delete mode 100644 login-utils/last.1.orig delete mode 100644 login-utils/last.c.orig mode change 100644 => 100755 misc-utils/chkdupexe.pl delete mode 100644 misc-utils/hostname.c.orig create mode 100644 mkminix-0.1/README create mode 100644 mkminix-0.1/linux/minix_fs.h create mode 100644 mkminix-0.1/mkmin-dj.h create mode 100644 mkminix-0.1/mkminix.diff create mode 100644 mount/getusername.c create mode 100644 mount/getusername.h create mode 100644 mount/mntent.c create mode 100644 mount/mntent.h create mode 100644 mount/mount_by_label.c create mode 100644 mount/mount_by_label.h create mode 100644 mount/mount_guess_fstype.c create mode 100644 mount/mount_guess_fstype.h create mode 100644 mount/swap_constants.h delete mode 100644 sys-utils/lpcntl.8 delete mode 100644 sys-utils/lpcntl.c rename sys-utils/{sln.1 => sln.8} (64%) delete mode 100644 uio.h-diff delete mode 100644 util-linux-2.1.Announce delete mode 100644 util-linux-2.1.bin.Notes delete mode 100644 util-linux-2.1.lsm diff --git a/ANNOUNCE b/ANNOUNCE index 0d762863..1eed25ef 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,14 +1,14 @@ -util-linux-2.8.tar.gz (source only distribution) +util-linux-2.9.tar.gz (source only distribution) READ the README file and the stuff below. -util-linux-2.8.tar.gz (source only distribution) +util-linux-2.9.tar.gz (source only distribution) NOTE: Before installing util-linux. READ the README or risk nuking your system. Thank you. Util-linux is a suite of essential utilities for any Linux system. -It's primary audience is system integrators (like the people at Debian +Its primary audience is system integrators (like the people at Debian and RedHat) and DIY Linux hackers. The rest of you will get a digested version of util-linux installed with no risk to your sanity. @@ -20,12 +20,13 @@ and Linux 2.0/Libc 5 and has also been tested with libc 6 on intel, alpha and sparc. People are encouraged to make _nice_ patches to util-linux and submitting them to util-linux@math.uio.no. Thank you. -Util-Linux 2.8 is imediately available from - ftp.math.uio.no:/pub/linux, and - sunsite.uio.no:/pub/unix/linux/packages/util-linux, -and will appear at - sunsite.unc.edu:/pub/Linux/system/Misc, as well as +Util-Linux 2.9 is imediately available from + ftp.win.tue.nl:/pub/linux/util +and will probably appear soon at + ftp.math.uio.no:/pub/linux + sunsite.uio.no:/pub/unix/linux/packages/util-linux + sunsite.unc.edu:/pub/Linux/system/Misc tsx-11.mit.edu:/pub/linux/packages/utils -when the people in charge there get time. -Nicolai Langfeldt +Andries Brouwer + diff --git a/README b/HISTORY similarity index 86% rename from README rename to HISTORY index cf30bf0a..f0ccc9ab 100644 --- a/README +++ b/HISTORY @@ -1,50 +1,104 @@ -util-linux 2.8: +util-linux 2.9i: + +* fixed 2.9h typo in more +* added -m: `Monday is 1st day' option to cal (Jean-Francois Bignolles) +* changed PAM stuff in login.c (+- mjohnson) +* added warning to cfdisk in case of multiple bootable partitions +* added 2048-byte sector support in fdisk (Oliver Schaertel) + +util-linux 2.9h: + +* mount recognizes "uid=useruid" and "gid=usergid" in /etc/fstab. +* documented the fact that "mount -t smb" will call /sbin/mount.smb. +* mount gives clear error message when fstab does not end in newline. +* swapon checks mode of file +* cfdisk got a more specific exit status (Enrique Zanardi) + +util-linux 2.9g: + +* mount updates (locking, "users" keyword, "/etc/filesystems", + "proto" and "vers" options in nfsmount, ...) + +util-linux 2.9f: + +* made ul handle lines of arbitrary length (Scott Maxwell) +* killed some C/H/S nonsense in fdisk +* fixes for archs with unsigned char type (Ambrose Li) +* fdisk fixes for power pc (Tom Rini) +* added a define for NCURSES_CONST +* fixes for list of signals in kill.c +* fixes for user name length in last.c + +util-linux 2.9e: + +* added a forgotten declaration to login.c (Christian Oyarzun) -WARNING: THE PROGRAMS IN THIS SUITE DO *NOT* SUPPORT SHADOW PASSWORD FILES! - UNLESS YOU USE PAM. +util-linux 2.9d: -WARNING: THIS COLLECTION CONFLICTS WITH SYSTEM V INITTAB. - UNLESS YOU CONFIGURE IT NOT TO. +* fixed segfault in umount caused by Wilcox' patch (Steffen Zahn) +* added lnz stuff to fdisk -WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY! +util-linux 2.9c: -WARNING: DO *NOT* INSTALL WITHOUT THINKING. +* refixed PAM stuff in login.c that was broken in 2.8. -WARNING: The simpleinit and some other programs in this package are - *NOT* System V compliant. These utilities are meant to be - used by people who build their own systems. If you are not - a wizard, do *NOT* blindly install these utilities: they could - prevent you from logging into your system. Have a boot floppy - ready, especially if you don't know what you are doing. It's a - great way to learn though ;-) +util-linux 2.9b: +* split README into INSTALL and HISTORY +* added a sentence to swapon.8 +* behaviour of write on non-ASCII fixed +* hwclock adapted to survive a failing mktime() -To install from source: +util-linux 2.9a: -1) Get source distribution (see the .lsm file for locations) -2) Untar util-linux-2.8.tar.gz in /usr/src -3) cd util-linux-2.8 -4) Edit MCONFIG -5) make -6) make install -7) If you want to use simpleinit and agetty, then make softlinks from - /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure - that your /etc/inittab is set up right (this is *NOT* the System V - compatible init!), or you will be hosed. If you are using the SysV - init and/or some other getty, they you can keep using those. +* added an include to lib/my_reboot.c so that __GLIBC__ is defined +* added setlocale() to login-utils/chfn.c +* do not recompute MAIL in login-utils/login.c + +util-linux 2.9: + +HIGHLIGHTS for version 2.9: + +1) Removed programs: + - strings. There is a version in binutils. + - frag. (Moved to historic in 2.4, crept back in 2.5. Gone again.) +1a) Not yet removed program: + - setfdprm. It also is in fdutils-5.2 (with an exceptionally + ugly man page). +1b) Removed directory: + - bsd. (The routine getopt() is in libc. err() moved to lib.) +2) Improvements: + - ddate has been fixed to count down to the new, right X-day + - look is now willing to search non-English dictionaries + (i.e., uses locale) + - cal now knows that Dutch day abbreviations have length 2 only + - mcookie does not block when no random stuff is available + - shutdown got a configuration file /etc/shutdown.conf + - fdisk now reads SGI disk labels (thanks to Andreas Neuper) + - mkswap now knows about new swap areas; mkswap.8 has been rewritten + - umount knows about umount2() and forced unmounting of nfs mounts + (however, I don't think it really works) + - mount is now willing to handle file names with embedded spaces + - mount can now mount things by UUID or volume name +3) Uglifications: + - swap.h has been replaced by a private swap_constants.h since + does not compile + - reboot has become a private routine, since libc5 and glibc2 conflict + - a mkminix-0.1 directory contains some patches to let mkfs.minix + work under DOS. (Untested.) +4) Numerous other small changes. + +0xF) Send questions and/or patches to util-linux@math.uio.no + +util-linux 2.8: HIGHLIGHTS for version 2.8: -0a) It's been way to long since the last release. My fault. -0b) NO PAM patches. 1) New programs: - getopt(1) by Frodo Looijaard replaces the older bsd based version. Keywords: Backward compatible, supports --long options. 1) Removed programs: - chroot: is no longer in util-linux. Get it free with GNU sh-utils - - frag: - - lpcntl: This was removed in an earlier release (2.7) but I forgot to - mention it. - hostid: No-one could figure out the right way for this program to work. Another hostid program is included in poeigl (see the LSM, Primary-site: ftp.daimi.aau.dk /pub/linux/poe) @@ -54,7 +108,6 @@ HIGHLIGHTS for version 2.8: are encouraged to send patches. 3) rev now only limits linelength to memory capacity 4) dmesg now uses a buffer that matches the kernel buffer in size (8KB) -0xF) Send questions and/or patches to util-linux@math.uio.no util-linux 2.7: @@ -65,12 +118,13 @@ HIGLIGHTS for version 2.7: converted to use terminfo (instead of termcap). 2) Removed progams: - - clock: Dropped entierly. Use hwclock (included). + - clock: Dropped entirely. Use hwclock (included). - sync: is in gnu fileutils. - setserial: Is being maintained by Ted Ts'o, he recommends setserial-2.12 (2.13 is bad luck) - clear: Included in ncurses - hostname, domainname, dnsdomainname: It's in net-utils. + - lpcntl. 3) Bugfixes, additions: - cfdisk: A much improved version. All known bugs have been fixed. @@ -86,11 +140,11 @@ HIGLIGHTS for version 2.7: ways to deal with this: - Don't run rpcgen, the needed pre-generated sources are included (nfsmount_xdr.c). You must hack mount/Makefile to do this. - - Edit the source emited by rpcgen so it can compile. This is very + - Edit the source emitted by rpcgen so it can compile. This is very simple if you know C. - Disable the NFS parts of mount. You have to edit mount/Makefile to do this. - - Use some other rpcgen + - Use some other rpcgen. util-linux 2.6.1 @@ -125,7 +179,7 @@ HIGHLIGHTS for version 2.6: UPDATES TO: util-linux@math.uio.no. 1) Removed programs: - - md5sum: available in GNU textutils. + - md5sum, dsplit: available in GNU textutils. - syslogd: Sysklogd is now prefered. It is available at tsx-11.mit.edu:/pub/sources/sbin sunsite.unc.edu:/pub/Linux/system/Daemons @@ -338,7 +392,7 @@ login-utils: vipw: 5.16 (Berkeley) 3/3/91, with modifications by Mike Grupenhoff wall: 8.2 (Berkeley) 11/16/93 (With changes so that damaging escape - sequences cannot be sent. + sequences cannot be sent.) ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin @@ -357,6 +411,8 @@ misc-utils: gatekeeper.dec.com:/pub/usenet/comp.sources.misc/volume40/dsplit getopt (getoptprog): jhunix.hcf.jhu.edu: /pub/public_domain_software/NetBSD/usr/src/usr.bin/getopt + replaced by getopt-1.0.3.tar.gz from Frodo Looijaard, + found at http://huizen.dds.nl/~frodol hostid: Mitch DSouza (m.dsouza@mrc-apu.cam.ac.uk) ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz hostname/dnsdomainname: Peter Tobias @@ -455,7 +511,7 @@ sys-utils: rdev: almesber@nessie.cs.id.ethz.ch (Werner Almesberger), with modifications from Peter MacDonald, Stephen Tweedie (sct@dcs.ed.ac.uk), and Dave (gentzel@nova.enet.dec.com) - readprofile: Alessandro Rubini + readprofile: Alessandro Rubini from readprofile-2.0.tar.gz renice: 8.1 (Berkeley) 6/9/93 ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin setserial: Michael K. Johnson (johnsonm@stolaf.edu) re-released Rick diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..c6a463e8 --- /dev/null +++ b/INSTALL @@ -0,0 +1,57 @@ + +WARNING: THE PROGRAMS IN THIS SUITE DO *NOT* SUPPORT SHADOW PASSWORD FILES! + UNLESS YOU USE PAM. + +WARNING: THIS COLLECTION CONFLICTS WITH SYSTEM V INITTAB. + UNLESS YOU CONFIGURE IT NOT TO. + +WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY! + +WARNING: DO *NOT* INSTALL WITHOUT THINKING. + +WARNING: The simpleinit and some other programs in this package are + *NOT* System V compliant. These utilities are meant to be + used by people who build their own systems. If you are not + a wizard, do *NOT* blindly install these utilities: they could + prevent you from logging into your system. Have a boot floppy + ready, especially if you don't know what you are doing. It's a + great way to learn though ;-) + + +To install from source: + +1) Get source distribution (see the .lsm file for locations) +2) Untar util-linux-2.9.tar.gz somewhere +3) cd util-linux-2.9 +4) Edit MCONFIG +5) make +6) make install +7) If you want to use simpleinit and agetty, then make softlinks from + /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure + that your /etc/inittab is set up right (this is *NOT* the System V + compatible init!), or you will be hosed. If you are using the SysV + init and/or some other getty, they you can keep using those. + + +If you have compilation problems: + +- with -lcrypt: you forgot to edit MCONFIG and write HAVE_LIBCRYPT=no. +- in cfdisk or setterm: you forgot to edit MCONFIG and write HAVE_NCURSES=no + (or you forgot to write CURSESFLAGS=-I/usr/include/ncurses -DNCH=0)? +- in fdisksunlabel.c: change #if 1 into #if 0 if there is no . +- in mount/nfsmount.c: change #if 1 into #if 0 if there is no inet_aton(). +- in sys-utils/ipcs.c: change #if 0 into #if 1 if is needed. +- in sys-utils/cytune.c: change #if 0 into #if 1 if is needed. + +elsewhere: tell util-linux@math.uio.no about it. + + +If you have runtime problems: + +- with non-ASCII characters: perhaps you forgot to set LC_CTYPE or LC_ALL? + (For example, in Norway one can say LC_ALL=no_NO; export LC_ALL and + then various utilities will treat Scandinavian non-ASCII letters as + letters.) + +otherwise: tell util-linux@math.uio.no about it. + diff --git a/LSM b/LSM index 0906306c..41edbbf3 100644 --- a/LSM +++ b/LSM @@ -1,22 +1,23 @@ Begin3 Title: util-linux: Miscellaneous utilities for Linux -Version: 2.8 +Version: 2.9g Description: agetty arch cal cfdisk chfn chkdupexe chsh clear hwclock col colcrt colrm column ctrlaltdel - cytune ddate dmesg dsplit fastboot fasthalt fdformat + cytune ddate dmesg fastboot fasthalt fdformat fdisk fsck.minix getopt halt hexdump ipcrm ipcs kbdrate kill last logger login look mcookie mesg mkfs mkfs.minix mkswap more mount namei passwd ramsize rdev readprofile reboot renice reset rev rootflags script setfdprm setsid setterm sfdisk shutdown simpleinit sln - strings swapdev swapoff swapon tsort tunelp ul umount + swapdev swapoff swapon tsort tunelp ul umount vidmode vipw wall whereis write Keywords: essential utilities Author: several -Maintained-by: Nicolai Langfeldt and others -Primary-site: ftp.math.uio.no /pub/linux - ~567k util-linux-2.8.tar.gz +Maintained-by: Andries Brouwer and others +Primary-site: ftp.win.tue.nl /pub/linux/util +Alternate-site: ftp.math.uio.no /pub/linux + ~567k util-linux-2.9g.tar.gz Alternate-site: sunsite.uio.no /pub/unix/linux/packages/util-linux Alternate-site: sunsite.unc.edu /pub/Linux/system/misc Alternate-site: tsx-11.mit.edu /pub/linux/packages/utils diff --git a/MAINTAINERS b/MAINTAINERS index 623bd520..623b7788 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,19 +1,6 @@ -util-linux is maintained by a group of people, all reachable at -util-linux@math.uio.no. +util-linux is maintained by a group of people +(Rik, Andries, Peter, Michael, Erik, Nicolai), +all reachable at util-linux@math.uio.no. -Some have specific interests, others just do everything else. - -This is a partial list of interests: - -Rik: Founding father -Andries: *fdisk, mount, ... -Peter: login, passwd, simpleinit, agetty, last, newgrp, shutdown, - domainname, ctrlaltdel -Michael: Spirit of advice -Erik: General hackery -Nicolai: mail-queue processor (batch oriented) - -Bryan: hwclock master, he's not on the list but the mail queue - processor forwards mail to him. - -Unassigned programs (defaulting to Nicolai): chfn, chsh, write, wall, ... +Bryan, the hwclock master, is not on the list +but the mail queue processor forwards mail to him. diff --git a/MCONFIG b/MCONFIG index 2823988e..147fc1ae 100644 --- a/MCONFIG +++ b/MCONFIG @@ -1,32 +1,32 @@ # MCONFIG -- Configuration stuff for util-linux # Created: Sat Feb 4 15:50:30 1995 -# Revised: Sun Nov 10 20:10:13 1996 by faith@cs.unc.edu # Copyright 1995 Rickard E. Faith (faith@cs.unc.edu) +# For a user-mode install, make (at least) three changes: +# - remove the `-o root' part in INSTALLSUID +# - set USE_TTY_GROUP=no +# - define DESTDIR + # Select for CPU one of intel, alpha, sparc, arm, m68k, mips CPU=$(shell uname -m | sed s/i.86/intel/) # if HAVE_LIBCRYPT is "yes" -lcrypt will be used -HAVE_LIBCRYPT=no -# HAVE_LIBCRYPT=yes +HAVE_LIBCRYPT=yes # If HAVE_PAM is set to "yes", then login, chfn, chsh, and newgrp # will use PAM for authentication. Additionally, passwd will not be # installed as it is not PAM aware. HAVE_PAM=no -#HAVE_PAM=yes # If HAVE_SHADOW is set to "yes", then login, chfn, chsh, newgrp, passwd, # and vipw will not be built or installed from the login-utils # subdirectory. -HAVE_SHADOW=no -#HAVE_SHADOW=yes +HAVE_SHADOW=yes # If HAVE_PASSWD is set to "yes", then passwd will not be built or # installed from the login-utils subdirectory (but login, chfn, chsh, # newgrp, and vipw *will* be installed). HAVE_PASSWD=no -#HAVE_PASSWD=yes # If you use chfn and chsh from this package, REQUIRE_PASSWORD will require # non-root users to enter the account password before updating /etc/passwd. @@ -44,21 +44,18 @@ ONLY_LISTED_SHELLS=yes # be built or installed from the login-utils subdirectory. (The shutdown # and halt that come with the SysVinit package should be used with the init # found in that package.) -#HAVE_SYSVINIT=no HAVE_SYSVINIT=yes # If HAVE_SYSVINIT_UTILS is set to "yes", then last, mesg, and wall will # not be built or installed from the login-utils subdirectory. (The # shutdown and init from the SysVinit package do not depend on the last, # mesg, and wall from that package.) -#HAVE_SYSVINIT_UTILS=no HAVE_SYSVINIT_UTILS=yes # If HAVE_GETTY is set to "yes", then agetty will not be built or # installed from the login-utils subdirectory. Note that agetty can # co-exist with other gettys, so this option should never be used. HAVE_GETTY=no -#HAVE_GETTY=yes # If USE_TTY_GROUP is set to "yes", then wall and write will be installed # setgid to the "tty" group, and mesg will only set the group write bit. @@ -67,24 +64,18 @@ HAVE_GETTY=no # xterm will do it correctly if X is compiled with USE_TTY_GROUP set # properly.] USE_TTY_GROUP=yes -#USE_TTY_GROUP=no -# If HAVE_STRINGS is set to "yes", then strings won't be installed. This -# is the quick fix until the strings in GNU binutils is in wide use and has -# internationalization support. -#HAVE_STRINGS=no -HAVE_STRINGS=yes +# If HAVE_OPENPTY is set to "yes", then script will use the Unix98 ptys +HAVE_OPENPTY=no # If HAVE_RESET is set to "yes", then reset won't be installed. The version # of reset that comes with the ncurses package is less aggressive. -#HAVE_RESET=no HAVE_RESET=yes -# If HAVE_MOUNT is set to "yes", then mount won't be installed, since many -# folks grab mount independenty of util-linux -# When util-linux is released it always contains the very latest mount. -HAVE_MOUNT=no -# HAVE_MOUNT=yes +# If HAVE_SLN is set to "yes", then sln won't be installed +# (but the man page sln.8 will be installed anyway). +# sln also comes with libc and glibc. +HAVE_SLN=no CC= gcc @@ -99,11 +90,15 @@ else endif endif -BSD= ../bsd +ERR_O=$(LIB)/err.o + +LIB=../lib LDFLAGS = -s WARNFLAGS = -Wall -CFLAGS = $(OPT) -I. -I$(BSD) $(WARNFLAGS) $(CURSESFLAGS) $(SLANGFLAGS) \ + +CFLAGS = $(OPT) -I. -I$(LIB) $(WARNFLAGS) \ + $(CURSESFLAGS) $(SLANGFLAGS) \ $(EXTRACFLAGS) \ -DSBINDIR=\"$(SBINDIR)\" \ -DUSRSBINDIR=\"$(USRSBINDIR)\" \ @@ -123,7 +118,7 @@ HAVE_NCURSES=yes # No such subdirectory - is the ncurses one. # CURSESFLAGS=-DNCH=0 # Pick your choice. -CURSESFLAGS=-DNCH=0 +CURSESFLAGS=-I/usr/include/ncurses -DNCH=0 LIBCURSES=-lncurses # Set HAVE_SLANG to yes if you have slang (and prefer to use that for cfdisk) @@ -147,11 +142,11 @@ BINDIR= $(DESTDIR)/bin VARPATH= $(DESTDIR)/var LOGDIR= $(DESTDIR)/var/log MANDIR= $(DESTDIR)/usr/man -MAN1DIR= $(DESTDIR)/usr/man/man1 -MAN3DIR= $(DESTDIR)/usr/man/man3 -MAN5DIR= $(DESTDIR)/usr/man/man5 -MAN6DIR= $(DESTDIR)/usr/man/man6 -MAN8DIR= $(DESTDIR)/usr/man/man8 +MAN1DIR= $(MANDIR)/man1 +MAN3DIR= $(MANDIR)/man3 +MAN5DIR= $(MANDIR)/man5 +MAN6DIR= $(MANDIR)/man6 +MAN8DIR= $(MANDIR)/man8 INFODIR= $(DESTDIR)/usr/info # Directory for shutdown, halt, reboot, etc. @@ -169,7 +164,7 @@ BINMODE= 755 MANMODE= 644 DATMODE= 644 INFOMODE= 644 -SUIDMODE= 4711 +SUIDMODE= 4755 CHMOD= chmod INSTALL= install diff --git a/Makefile b/Makefile index 5bbbdc25..92c9cae5 100644 --- a/Makefile +++ b/Makefile @@ -5,21 +5,18 @@ # May be distributed under the terms of the GNU GPL. # -VERSION=2.8 +VERSION=2.9 include ./MCONFIG -ifeq "$(HAVE_MOUNT)" "no" - MOUNTDIR=mount -endif - -SUBDIRS= bsd \ - getopt \ +SUBDIRS=lib \ + getopt-1.0.3a \ disk-utils \ games \ login-utils \ misc-utils \ - $(MOUNTDIR) \ + mount \ + fdisk \ sys-utils \ text-utils diff --git a/attic/pidof.c b/attic/pidof.c new file mode 100644 index 00000000..74709c78 --- /dev/null +++ b/attic/pidof.c @@ -0,0 +1,95 @@ +/* pid -- display the process id of a running command + + Copyright (c) 1994 Salvatore Valente + Copyright (c) 1996 Bruno Haible + + 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 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#include +#include +#include + +extern int* get_pids (char*, int); + +char version_string[] = "pid 1.0"; +char* program_name; + +int usage (int status) +{ + FILE* fp = (status == 0 ? stdout : stderr); + fprintf(fp, "Usage: %s command ...\n", program_name); + return status; +} + +static int compar_int (const void* i1, const void* i2) +{ + return *((int *)i1) - *((int *)i2); +} + +int main (int argc, char *argv[]) +{ + int i; + int *pids, *pids0; + int num_allpids = 0; + int *allpids = (int*)0; + int allpids_size = 0; + + program_name = argv[0]; + + /* Argument processing. */ + for (i = 1; i < argc; i++) { + char* arg = argv[i]; + if (!strcmp(arg, "--help")) + return usage(0); + else if (!strcmp(arg, "--version")) { + printf("%s\n", version_string); + return 0; + } + } + + /* Gather the pids. */ + for (i = 1; i < argc; i++) { + char* arg = argv[i]; + pids0 = pids = get_pids(arg, 1); + if (pids) { + while (*pids >= 0) { + int pid = *pids++; + if (num_allpids >= allpids_size) { + allpids_size = 2*allpids_size+1; + allpids = (int*) realloc(allpids, sizeof(int)*allpids_size); + if (!allpids) { + fprintf(stderr, "%s: out of memory\n", program_name); + exit(1); + } + } + allpids[num_allpids++] = pid; + } + free(pids0); + } + } + + /* Sort them. */ + if (num_allpids > 1) + qsort(allpids, num_allpids, sizeof(int), compar_int); + + /* Print them. */ + for (pids = allpids, i = num_allpids; i > 0; pids++, i--) + printf("%d\n", *pids); + + return 0; +} diff --git a/text-utils/strings.1 b/attic/strings.1 similarity index 100% rename from text-utils/strings.1 rename to attic/strings.1 diff --git a/text-utils/strings.c b/attic/strings.c similarity index 100% rename from text-utils/strings.c rename to attic/strings.c diff --git a/bsd/Makefile b/bsd/Makefile deleted file mode 100644 index 8783c5b3..00000000 --- a/bsd/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Makefile -- Makefile for util-linux Linux utilities -# Created: Sat Dec 26 20:09:40 1992 -# Revised: Fri Mar 10 21:20:41 1995 by faith@cs.unc.edu -# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) -# - -include ../MCONFIG - -all: err.o getopt.o -err.o: err.c -getopt.o: getopt.c - -.PHONY: clean distclean -clean: - -rm -f *.o *~ core - -install install.shadow: diff --git a/bsd/getopt.3 b/bsd/getopt.3 deleted file mode 100644 index c21a0a72..00000000 --- a/bsd/getopt.3 +++ /dev/null @@ -1,210 +0,0 @@ -.\" Copyright (c) 1988, 1991 Regents of the University of California. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getopt.3 6.16 (Berkeley) 4/19/91 -.\" -.Dd April 19, 1991 -.Dt GETOPT 3 -.Os BSD 4.3 -.Sh NAME -.Nm getopt -.Nd get option letter from argv -.Sh SYNOPSIS -.Fd #include -.Vt extern char *optarg -.Vt extern int optind -.Vt extern int opterr -.Ft int -.Fn getopt "int argc" "char * const *argv" "const char *optstring" -.Sh DESCRIPTION -The -.Fn getopt -function gets -the next -.Em known -option character from -.Fa argv . -An option character is -.Em known -if it has been specified in the string of accepted option characters, -.Fa optstring . -.Pp -The option string -.Fa optstring -may contain the following characters; letters and -letters followed by a colon to indicate an option argument -is to follow. It does not matter to -.Fn getopt -if a following argument has leading white space. -.Pp -On return from -.Fn getopt , -.Va optarg -points to an option argument, if it is anticipated, -and the variable -.Va optind -contains the index to the next -.Fa argv -argument for a subsequent call -to -.Fn getopt . -.Pp -The variable -.Va opterr -and -.Va optind -are both initialized to 1. -In order to use -.Fn getopt -to evaluate multiple sets of arguments, or to evaluate a single set of -arguments multiple times, -.Va optind -must be initialized to the number of argv entries to be skipped in each -evaluation. -.Pp -The -.Fn getopt -function -returns an -.Dv EOF -when the argument list is exhausted, or a non-recognized -option is encountered. -The interpretation of options in the argument list may be cancelled -by the option -.Ql -- -(double dash) which causes -.Fn getopt -to signal the end of argument processing and return an -.Dv EOF . -When all options have been processed (i.e., up to the first non-option -argument), -.Fn getopt -returns -.Dv EOF . -.Sh DIAGNOSTICS -If the -.Fn getopt -function encounters a character not found in the string -.Va optarg -or detects -a missing option argument -it writes error message -.Ql ? -to the -.Em stderr . -Setting -.Va opterr -to a zero will disable these error messages. -.Sh EXAMPLE -.Bd -literal -compact -extern char *optarg; -extern int optind; -int bflag, ch, fd; - -bflag = 0; -while ((ch = getopt(argc, argv, "bf:")) != EOF) - switch(ch) { - case 'b': - bflag = 1; - break; - case 'f': - if ((fd = open(optarg, O_RDONLY, 0)) < 0) { - (void)fprintf(stderr, - "myname: unable to read file %s.\en", optarg); - exit(1) ; - } - break; - case '?': - default: - usage(); -} -argc -= optind; -argv += optind; -.Ed -.Sh HISTORY -The -.Fn getopt -function appeared -.Bx 4.3 . -.Sh BUGS -Option arguments are allowed to begin with -.Dq Li \- ; -this is reasonable but -reduces the amount of error checking possible. -.Pp -A single dash -.Dq Li - -may be specified as an character in -.Fa optstring , -however it should -.Em never -have an argument associated with it. -This allows -.Fn getopt -to be used with programs that expect -.Dq Li - -as an option flag. -This practice is wrong, and should not be used in any current development. -It is provided for backward compatibility -.Em only . -By default, a single dash causes -.Fn getopt -to return -.Dv EOF . -This is, we believe, compatible with System V. -.Pp -It is also possible to handle digits as option letters. -This allows -.Fn getopt -to be used with programs that expect a number -.Pq Dq Li \&-\&3 -as an option. -This practice is wrong, and should not be used in any current development. -It is provided for backward compatibility -.Em only . -The following code fragment works fairly well. -.Bd -literal -offset indent -int length; -char *p; - -while ((c = getopt(argc, argv, "0123456789")) != EOF) - switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - p = argv[optind - 1]; - if (p[0] == '-' && p[1] == ch && !p[2]) - length = atoi(++p); - else - length = atoi(argv[optind] + 1); - break; - } -} -.Ed diff --git a/bsd/getopt.c b/bsd/getopt.c deleted file mode 100644 index be621bd9..00000000 --- a/bsd/getopt.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -/* - * get option letter from argument vector - */ -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt; /* character checked for validity */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define EMSG "" - -int -getopt(nargc, nargv, ostr) - int nargc; - char * const *nargv; - const char *ostr; -{ - static char *place = EMSG; /* option letter processing */ - register char *oli; /* option letter list index */ - char *p; - - if (!*place) { /* update scanning pointer */ - if (optind >= nargc || *(place = nargv[optind]) != '-') { - place = EMSG; - return(EOF); - } - if (place[1] && *++place == '-') { /* found "--" */ - ++optind; - place = EMSG; - return(EOF); - } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || - !(oli = index(ostr, optopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means EOF. - */ - if (optopt == (int)'-') - return(EOF); - if (!*place) - ++optind; - if (opterr) { - if (!(p = rindex(*nargv, '/'))) - p = *nargv; - else - ++p; - (void)fprintf(stderr, "%s: illegal option -- %c\n", - p, optopt); - } - return(BADCH); - } - if (*++oli != ':') { /* don't need argument */ - optarg = NULL; - if (!*place) - ++optind; - } - else { /* need an argument */ - if (*place) /* no white space */ - optarg = place; - else if (nargc <= ++optind) { /* no arg */ - place = EMSG; - if (!(p = rindex(*nargv, '/'))) - p = *nargv; - else - ++p; - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - p, optopt); - return(BADCH); - } - else /* white space */ - optarg = nargv[optind]; - place = EMSG; - ++optind; - } - return(optopt); /* dump back option letter */ -} diff --git a/disk-utils/Makefile b/disk-utils/Makefile index d21cedb9..aec38630 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -23,48 +23,12 @@ 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 -ifneq "$(CPU)" "m68k" -MAN8:=$(MAN8) fdisk.8 cfdisk.8 sfdisk.8 -SBIN:=$(SBIN) fdisk cfdisk sfdisk -endif -else -MAN8:=$(MAN8) fdisk.8 -SBIN:=$(SBIN) fdisk endif # Where to put datebase files? all: $(SBIN) $(USRBIN) -cfdisk.o: cfdisk.c -ifeq "$(HAVE_SLANG)" "yes" - $(CC) -c $(CFLAGS) -DSLCURSES=1 $< -o $@ -else -ifeq "$(HAVE_NCURSES)" "yes" - $(CC) -c $(CFLAGS) $< -o $@ -else - : -endif -endif - -cfdisk: cfdisk.o llseek.o -ifeq "$(HAVE_SLANG)" "yes" - $(CC) $(LDFLAGS) $^ -o $@ $(LIBSLANG) -else -ifeq "$(HAVE_NCURSES)" "yes" - $(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES) -lm -else - @echo $@ not made since it requires ncurses or slang -endif -endif - -# not installed by default -activate: sfdisk - rm -f activate - ln -s sfdisk activate - -# Rules for everything else - fdformat: fdformat.o fsck.minix: fsck.minix.o fsck.minix.o: fsck.minix.c bitops.h @@ -73,17 +37,6 @@ mkfs.minix: mkfs.minix.o mkfs.minix.o: mkfs.minix.c bitops.h mkswap: mkswap.o setfdprm: setfdprm.o -sfdisk: sfdisk.o - -ifeq "$(CPU)" "sparc" -fdisk: fdisk.o fdisklabel.o fdisksunlabel.o llseek.o -fdisksunlabel.o: fdisksunlabel.c fdisksunlabel.h fdisk.h -else -fdisk: fdisk.o fdisklabel.o llseek.o -endif - -fdisk.o: fdisk.c fdisk.h -fdisklabel.o: fdisklabel.c fdisk.h fdisklabel.h install: all $(INSTALLDIR) $(SBINDIR) $(USRBINDIR) $(ETCDIR) diff --git a/disk-utils/cfdisk.8.bak b/disk-utils/cfdisk.8.bak deleted file mode 100644 index cb23149f..00000000 --- a/disk-utils/cfdisk.8.bak +++ /dev/null @@ -1,407 +0,0 @@ -.\" cfdisk.8 -- man page for cfdisk -.\" Copyright 1994 Kevin E. Martin (martin@cs.unc.edu) -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" " for hilit mode -.TH CFDISK 8 "25 April 1994" "The BOGUS Linux Release" "Linux Programmer's Manual" -.SH NAME -cfdisk \- Curses based disk partition table manipulator for Linux -.SH SYNOPSIS -.BI "cfdisk [ \-avz ] [ \-c " cylinders " ] [ \-h " heads " ]" -.BI "[ \-s " sectors-per-track " ] [ -P " opt " ] [ " device " ]" -.SH DESCRIPTION -.B cfdisk -is a curses based program for partitioning a hard disk drive. The -.I device -can be any one of the following: -.sp -.nf -.RS -/dev/hda [default] -/dev/hdb -/dev/sda -/dev/sdb -/dev/sdc -/dev/sdd -.RE -.fi - -.B cfdisk -first tries to read the geometry of the hard disk. If it fails, an -error message is displayed and -.B cfdisk -exits. This should only happen when partitioning a SCSI drive on an -adapter without a BIOS. To correct this problem, you can set the -.IR cylinders ", " heads " and " sectors-per-track -on the command line. Next, -.B cfdisk -tries to read the current partition table from the disk drive. If it -is unable to figure out the partition table, an error is displayed and -the program will exit. This might also be caused by incorrect -geometry information, and can be overridden on the command line. -Another way around this problem is with the -.B \-z -option. This will ignore the partition table on the disk. - -The main display is composed of four sections, from top to bottom: the -header, the partitions, the command line and a warning line. The -header contains the program name and version number followed by the -disk drive and its geometry. The partitions section always displays -the current partition table. The command line is the place where -commands and text are entered. The available commands are usually -displayed in brackets. The warning line is usually empty except when -there is important information to be displayed. The current partition -is highlighted with reverse video (or an arrow if the -.B \-a -option is given). All partition specific commands apply to the -current partition. - -The format of the partition table in the partitions section is, from -left to right: Name, Flags, Partition Type, Filesystem Type and Size. -The name is the partition device name. The flags can be -.IR Boot , -which designates a bootable partition or -.IR NC , -which stands for "Not Compatible with DOS or OS/2". DOS, OS/2 and -possibly other operating systems require the first sector of the first -partition on the disk and all logical partitions to begin on the -second head. This wastes the second through the last sector of the -first track of the first head (the first sector is taken by the -partition table itself). -.B cfdisk -allows you to recover these "lost" sectors with the maximize command -.RB ( m ). -.I Note: -.BR fdisk (8) -and some early versions of DOS create all partitions with the number -of sectors already maximized. For more information, see the maximize -command below. The partition type can be one of -.IR Primary " or " Logical . -For unallocated space on the drive, the partition type can also be -.IR Pri/Log , -or empty (if the space is unusable). The filesystem type section -displays the name of the filesystem used on the partition, if known. -If it is unknown, then -.I Unknown -and the hex value of the filesystem type are displayed. A special -case occurs when there are sections of the disk drive that cannot be -used (because all of the primary partitions are used). When this is -detected, the filesystem type is displayed as -.IR Unusable . -The size field displays the size of the partition in megabytes (by -default). It can also display the size in sectors and cylinders (see -the change units command below). If an asterisks -.RB ( * ) -appears after the size, this means that the partition is not aligned -on cylinder boundaries. -.SH "DOS 6.x WARNING" - -The DOS 6.x FORMAT command looks for some information in the first -sector of the data area of the partition, and treats this information -as more reliable than the information in the partition table. DOS -FORMAT expects DOS FDISK to clear the first 512 bytes of the data area -of a partition whenever a size change occurs. DOS FORMAT will look at -this extra information even if the /U flag is given -- we consider -this a bug in DOS FORMAT and DOS FDISK. - -The bottom line is that if you use cfdisk or fdisk to change the size of a -DOS partition table entry, then you must also use -.B dd -to zero the first 512 bytes of that partition before using DOS FORMAT to -format the partition. For example, if you were using cfdisk to make a DOS -partition table entry for /dev/hda1, then (after exiting fdisk or cfdisk -and rebooting Linux so that the partition table information is valid) you -would use the command "dd if=/dev/zero of=/dev/hda1 bs=512 count=1" to zero -the first 512 bytes of the partition. -.B BE EXTREMELY CAREFUL -if you use the -.B dd -command, since a small typo can make all of the data on your disk useless. - -.B BE EXTREMELY CAREFUL -if you use the -.B dd -command, since a small typo can make all of the data on your disk useless. - -For best resutls, you should always use an OS-specific partition table -program. For example, you should make DOS partitions with the DOS FDISK -program and Linux partitions with the Linux fdisk or Linux cfdisk program. - -.SH COMMANDS -.B cfdisk -commands can be entered by pressing the desired key (pressing -.I Enter -after the command is not necessary). Here is a list of the available -commands: -.TP -.B b -Toggle bootable flag of the current partition. This allows you to -select which primary partition is bootable on the drive. -.TP -.B d -Delete the current partition. This will convert the current partition -into free space and merge it with any free space immediately -surrounding the current partition. A partition already marked as free -space or marked as unusable cannot be deleted. -.TP -.B g -Change the disk geometry (cylinders, heads, or sectors-per-track). -.B WARNING: -This option should only be used by people who know what they are -doing. A command line option is also available to change the disk -geometry. While at the change disk geometry command line, you can -choose to change cylinders -.RB ( c ), -heads -.RB ( h ), -and sectors per track -.RB ( s ). -The default value will be printed at the prompt which you can accept -by simply pressing the -.I Enter -key, or you can exit without changes by pressing the -.I ESC -key. If you want to change the default value, simply enter the -desired value and press -.IR Enter . -The altered disk parameter values do not take effect until you return -the main menu (by pressing -.IR Enter " or " ESC -at the change disk geometry command line. If you change the geometry -such that the disk appears larger, the extra sectors are added at the -end of the disk as free space. If the disk appears smaller, the -partitions that are beyond the new last sector are deleted and the -last partition on the drive (or the free space at the end of the -drive) is made to end at the new last sector. -.TP -.B h -Print the help screen. -.TP -.B m -Maximize disk usage of the current partition. This command will -recover the the unused space between the partition table and the -beginning of the partition, but at the cost of making the partition -incompatible with DOS, OS/2 and possibly other operating systems. -This option will toggle between maximal disk usage and DOS, OS/2, -etc. compatible disk usage. The default when creating a partition is -to create DOS, OS/2, etc. compatible partitions. -.TP -.B n -Create new partition from free space. If the partition type is -.IR Primary " or " Logical , -a partition of that type will be created, but if the partition type is -.IR Pri/Log , -you will be prompted for the type you want to create. Be aware that -(1) there are only four slots available for primary partitions and (2) -since there can be only one extended partition, which contains all of -the logical drives, all of the logical drives must be contiguous (with -no intervening primary partition). -.B cfdisk -next prompts you for the size of the partition you want to create. -The default size, equal to the entire free space of the current -partition, is display in megabytes. You can either press the -.I Enter -key to accept the default size or enter a different size at the -prompt. -.B cfdisk -accepts size entries in megabytes -.RB ( M ) -[default], kilobytes -.RB ( K ), -cylinders -.RB ( C ) -and sectors -.RB ( S ) -by entering the number immediately followed by one of -.RB ( M ", " K ", " C " or " S ). -If the partition fills the free space available, the partition is -created and you are returned to the main command line. Otherwise, the -partition can be created at the beginning or the end of the free -space, and -.B cfdisk -will ask you to choose where to place the partition. After the -partition is created, -.B cfdisk -automatically adjusts the other partition's partition types if all of -the primary partitions are used. -.TP -.B p -Print the partition table to the screen or to a file. There are -several different formats for the partition that you can choose from: -.sp -.RS -.TP -.B r -Raw data format (exactly what would be written to disk) -.TP -.B s -Partition table in sector order format -.TP -.B t -Partition table in raw format -.RE - -.RS -The -.I raw data format -will print the sectors that would be written to disk if a -.BR w rite -command is selected. First, the primary partition table is printed, -followed by the partition tables associated with each logical -partition. The data is printed in hex byte by byte with 16 bytes per -line. - -The -.I partition table in sector order format -will print the partition table ordered by sector number. The fields, -from left to right, are the number of the partition, the partition -type, the first sector, the last sector, the offset from the first -sector of the partition to the start of the data, the length of the -partition, the filesystem type (with the hex value in parenthesis), -and the flags (with the hex value in parenthesis). In addition to the -primary and logical partitions, free and unusable space is printed and -the extended partition is printed before the first logical partition. - -If a partition does not start or end on a cylinder boundary or if the -partition length is not divisible by the cylinder size, an asterisks -.RB ( * ) -is printed after the non-aligned sector number/count. This usually -indicates that a partition was created by an operating system that -either does not align partitions to cylinder boundaries or that used -different disk geometry information. If you know the disk geometry of -the other operating system, you could enter the geometry information -with the change geometry command -.RB ( g ). - -For the first partition on the disk and for all logical partitions, if -the offset from the beginning of the partition is not equal to the -number of sectors per track (i.e., the data does not start on the -first head), a number sign -.RB ( # ) -is printed after the offset. For the remaining partitions, if the -offset is not zero, a number sign will be printed after the offset. -This corresponds to the -.I NC -flag in the partitions section of the main display. - -The -.I partition table in raw format -will print the partition table ordered by partition number. It will -leave out all free and unusable space. The fields, from left to -right, are the number of the partition, the flags (in hex), the -starting head, sector and cylinder, the filesystem ID (in hex), the -ending head, sector and cylinder, the starting sector in the partition -and the number of sectors in the partition. The information in this -table can be directly translated to the -.IR "raw data format" . - -The partition table entries only have 10 bits available to represent -the starting and ending cylinders. Thus, when the absolute starting -(ending) sector number is on a cylinder greater than 1023, the maximal -values for starting (ending) head, sector and cylinder are printed. -This is the method used by OS/2, and thus fixes the problems -associated with OS/2's fdisk rewriting the partition table when it is -not in this format. Since Linux and OS/2 use absolute sector counts, -the values in the starting and ending head, sector and cylinder are -not used. -.RE -.TP -.B q -Quit program. This will exit the program without writing any data to -disk. -.TP -.B t -Change the filesystem type. By default, new partitions are created as -.I Linux -partitions, but since -.B cfdisk -can create partitions for other operating systems, change partition -type allows you to enter the hex value of the filesystem you desire. -A list of the know filesystem types is displayed. You can type in the -filesystem type at the prompt or accept the default filesystem type -.RI [ Linux ]. -.TP -.B u -Change units of the partition size display. It will rotate through -megabytes, sectors and cylinders. -.TP -.B W -Write partition table to disk (must enter an upper case W). Since -this might destroy data on the disk, you must either confirm or deny -the write by entering `yes' or `no'. If you enter `yes', -.B cfdisk -will write the partition table to disk and the tell the kernel to -re-read the partition table from the disk. The re-reading of the -partition table works is most cases, but I have seen it fail. Don't -panic. It will be correct after you reboot the system. In all cases, -I still recommend rebooting the system--just to be safe. -.TP -.I Up Arrow -.TP -.I Down Arrow -Move cursor to the previous or next partition. If there are more -partitions than can be displayed on a screen, you can display the next -(previous) set of partitions by moving down (up) at the last (first) -partition displayed on the screen. -.TP -.I CTRL-L -Redraws the screen. In case something goes wrong and you cannot read -anything, you can refresh the screen from the main command line. -.TP -.B ? -Print the help screen. - -.RE -All of the commands can be entered with either upper or lower case -letters (except for -.BR W rites). -When in a sub-menu or at a prompt to enter a filename, you can hit the -.I ESC -key to return to the main command line. -.SH OPTIONS -.TP -.B \-a -Use an arrow cursor instead of reverse video for highlighting the -current partition. -.TP -.B \-v -Print the version number and copyright. -.TP -.B \-z -Start with zeroed partition table. This option is useful when you -want to repartition your entire disk. -.I Note: -this option does not zero the partition table on the disk; rather, it -simply starts the program without reading the existing partition -table. -.TP -.BI \-c " cylinders" -.TP -.BI \-h " heads" -.TP -.BI \-s " sectors-per-track" -Override the number of cylinders, heads and sectors per track read -from the BIOS. If your BIOS or adapter does not supply this -information or if it supplies incorrect information, use these options -to set the disk geometry values. -.TP -.BI \-P " opt" -Prints the partition table in specified formats. -.I opt -can be one or more of "r", "s" or "t". See the -.BR p rint -command (above) for more information on the print formats. -.SH "SEE ALSO" -fdisk(8) -.SH BUGS -The current version does not support multiple disks (future addition). -.SH AUTHOR -Kevin E. Martin (martin@cs.unc.edu) diff --git a/disk-utils/cfdisk.c.bak b/disk-utils/cfdisk.c.bak deleted file mode 100644 index 3b9f22f5..00000000 --- a/disk-utils/cfdisk.c.bak +++ /dev/null @@ -1,2066 +0,0 @@ -/**************************************************************************** - * - * CFDISK - * - * cfdisk is a curses based disk drive partitioning program that can - * create partitions for a wide variety of operating systems including - * Linux, MS-DOS and OS/2. - * - * cfdisk was inspired by the fdisk program, by A. V. Le Blanc - * (LeBlanc@mcc.ac.uk). - * - * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - * - * cfdisk 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 2 of the License, or - * (at your option) any later version. - * - * cfdisk is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with cfdisk; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for BLKRRPART */ - -typedef long ext2_loff_t; -extern ext2_loff_t ext2_llseek(unsigned int fd, - ext2_loff_t offset, - unsigned int origin); - -#define VERSION "0.8 BETA (>2GB)" - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_CYLINDERS 65535 -#define MAX_HEADS 255 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 - -#define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define EXTENDED 0x05 -#define LINUX_MINIX 0x81 -#define LINUX_SWAP 0x82 -#define LINUX 0x83 - -#define ADD_EXISTS "This partition is already in use" -#define ADD_UNUSABLE "This partition is unusable" -#define DEL_EMPTY "Cannot delete an empty partition" -#define ID_EMPTY "Cannot change FS Type to empty" -#define ID_EXT "Cannot change FS Type to extended" -#define NEED_EXT "No room to create the extended partition" -#define NO_FLAGS "Cannot make this partition bootable" -#define NO_MORE_PARTS "No more partitions" -#define PRINT_OPEN_ERR "Cannot open file '%s'" -#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions" -#define TYPE_EMPTY "Cannot change the type of an empty partition" -#define BAD_COMMAND "Illegal command" -#define MAX_UNMAXABLE "Cannot maximize this partition" -#define BAD_OPEN "Cannot open disk drive" -#define BAD_SEEK "Cannot seek on disk drive" -#define BAD_READ "Cannot read disk drive" -#define BAD_WRITE "Cannot write disk drive" -#define BAD_GEOMETRY "Cannot read disk drive geometry" -#define BAD_PRIMARY "Bad primary partition" -#define BAD_LOGICAL "Bad logical partition" -#define BAD_CYLINDERS "Illegal cylinders value" -#define BAD_HEADS "Illegal heads value" -#define BAD_SECTORS "Illegal sectors value" -#define WRITE_WARN "Warning!! This may destroy data on your disk!" -#define YES_NO "Please enter `yes' or `no'" -#define WRITING_PART "Writing partition table to disk..." -#define YES_WRITE "Wrote partition table to disk" -#define NO_WRITE "Did not write partition table to disk" -#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." - -#define PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 20 - -#define CR '\015' -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' - -/* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 - -#define GS_DEFAULT -1 -#define GS_ESCAPE -2 - -#define PRINT_RAW_TABLE 1 -#define PRINT_SECTOR_TABLE 2 -#define PRINT_PARTITION_TABLE 4 - -#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4) -#define IS_LOGICAL(p) ((p) > 3) - -#define round_int(d) ((double)((int)(d+0.5))) -#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d))) - -#define set_hsc(h,s,c,sector) \ -{ \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xFF; \ - s |= (sector >> 2) & 0xC0;\ -} - -#define ALIGNMENT 2 -typedef union { - struct { - unsigned char align[ALIGNMENT]; - unsigned char b[SECTOR_SIZE]; - } c; - struct { - unsigned char align[ALIGNMENT]; - unsigned char buffer[0x1BE]; - struct partition part[4]; - unsigned short flag; - } p; -} partition_table; - -typedef struct { - int first_sector; /* first sector in partition */ - int last_sector; /* last sector in partition */ - int offset; /* offset from first sector to start of data */ - int flags; /* active == 0x80 */ - int id; /* filesystem type */ - int num; /* number of partition -- primary vs. logical */ -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; -int changed = FALSE; -int opened = FALSE; - -partition_info p_info[MAXIMUM_PARTS]; -partition_info ext_info; -int num_parts = 0; - -int logical = 0; -int logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int print_only = 0; - -/* Curses screen information */ -int cur_part = 0; -int warning_last_time = FALSE; -int defined = FALSE; -int COLUMNS = 80; -int NUM_ON_SCREEN = 1; - -/* Y coordinates */ -int HEADER_START = 0; -int DISK_TABLE_START = 5; -int WARNING_START = 23; -int COMMAND_LINE_Y = 21; - -/* X coordinates */ -int NAME_START = 4; -int FLAGS_START = 16; -int PTYPE_START = 30; -int FSTYPE_START = 45; -int SIZE_START = 70; -int COMMAND_LINE_X = 5; - -#define NUM_PART_TYPES 256 -char *partition_type[NUM_PART_TYPES] = { - [LINUX_MINIX] = "Linux/MINIX", - [LINUX_SWAP] = "Linux Swap", - [LINUX] = "Linux", - [FREE_SPACE] = "Free Space", - [EXTENDED] = "Extended", - [0x01] = "DOS 12-bit FAT", - [0x04] = "DOS 16-bit < 32Mb", - [0x06] = "DOS 16-bit >=32Mb", - [0x07] = "OS/2 HPFS", - [0x0A] = "OS/2 Boot Manager", - [0xA5] = "BSD/386", - -/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk) - * fdisk program. I do not know where they came from, but I include - * them for completeness. - */ - - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x40] = "Venix 80286", - [0x51] = "Novell?", - [0x52] = "Microport", - [0x63] = "GNU HURD", - [0x64] = "Novell", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xF2] = "DOS secondary", - [0xFF] = "BBT" -}; - -void fdexit(int ret) -{ - if (opened) - close(fd); - - if (changed) { - fprintf(stderr, "Disk has been changed.\n"); - fprintf(stderr, "Reboot the system to ensure the partition " - "table is correctly updated.\n"); - - fprintf( stderr, "\nWARNING: If you have created or modified any\n" - "DOS 6.x partitions, please see the cfdisk manual\n" - "page for additional information.\n" ); - } - - - exit(ret); -} - -int get_string(char *str, int len, char *def) -{ - char c; - int i = 0; - int x, y; - int use_def = FALSE; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - while ((c = getch()) != '\n' && c != CR) { - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: - if (i < len && isprint(c)) { - mvaddch(y, x+i, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - } else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -void clear_warning(void) -{ - int i; - - if (!warning_last_time) - return; - - move(WARNING_START,0); - for (i = 0; i < COLS; i++) - addch(' '); - - warning_last_time = FALSE; -} - -void print_warning(char *s) -{ - mvaddstr(WARNING_START, (COLS-strlen(s))/2, s); - putchar(BELL); /* CTRL-G */ - - warning_last_time = TRUE; -} - -void fatal(char *s) -{ - char str[LINE_LENGTH]; - - sprintf(str, "FATAL ERROR: %s", s); - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - - refresh(); - - (void)getch(); - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(1); -} - -void read_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); -} - -void write_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); -} - -void check_part_info(void) -{ - int i, pri = 0, log = 0; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED) - if (log > 0) - pri++; - else { - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; - } - - if (pri >= 4) - for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else - p_info[i].id = UNUSABLE; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - else /* if (pri < 4) */ - for (i = 0; i < num_parts; i++) { - if (p_info[i].id == UNUSABLE) - p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) - p_info[i].num = LOGICAL; - else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else - p_info[i].num = PRIMARY; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } -} - -void remove_part(int i) -{ - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; -} - -void insert_part(int i, int num, int id, int flags, int first, int last, - int offset) -{ - int p; - - for (p = num_parts; p > i; p--) - p_info[p] = p_info[p-1]; - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - num_parts++; -} - -void del_part(int i) -{ - int num = p_info[i].num; - - if (i > 0 && (p_info[i-1].id == FREE_SPACE || - p_info[i-1].id == UNUSABLE)) { - /* Merge with previous partition */ - p_info[i-1].last_sector = p_info[i].last_sector; - remove_part(i--); - } - - if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE || - p_info[i+1].id == UNUSABLE)) { - /* Merge with next partition */ - p_info[i+1].first_sector = p_info[i].first_sector; - remove_part(i); - } - - if (i > 0) - p_info[i].first_sector = p_info[i-1].last_sector + 1; - else - p_info[i].first_sector = 0; - - if (i < num_parts - 1) - p_info[i].last_sector = p_info[i+1].first_sector - 1; - else - p_info[i].last_sector = sectors*heads*cylinders - 1; - - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - - if (IS_LOGICAL(num)) { - /* We have a logical partition --> shrink the extended partition - * if (1) this is the first logical drive, or (2) this is the - * last logical drive; and if there are any other logical drives - * then renumber the ones after "num". - */ - if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) - ext_info.first_sector = p_info[i].last_sector + 1; - if (i == num_parts-1 || - (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num))) - ext_info.last_sector = p_info[i].first_sector - 1; - for (i = 0; i < num_parts; i++) - if (p_info[i].num > num) - p_info[i].num--; - } - - /* Clean up the rest of the partitions */ - check_part_info(); -} - -int add_part(int num, int id, int flags, int first, int last, int offset) -{ - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS || - first < 0 || - first >= cylinders*heads*sectors || - last < 0 || - last >= cylinders*heads*sectors) - return -1; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED && log > 0) - pri++; - - if (IS_PRIMARY(num)) - if (pri >= 4) - return -1; - else - pri++; - - for (i = 0; p_info[i].last_sector < first; i++); - - if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector) - return -1; - - if (id == EXTENDED) - if (ext_info.id != FREE_SPACE) - return -1; - else if (IS_PRIMARY(num)) { - ext_info.first_sector = first; - ext_info.last_sector = last; - ext_info.offset = offset; - ext_info.flags = flags; - ext_info.id = EXTENDED; - ext_info.num = num; - - return 0; - } else - return -1; - - if (IS_LOGICAL(num)) { - if (ext_info.id != EXTENDED) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); - } else { - /* We might have a logical partition outside of the extended - * partition's range --> we have to extend the extended - * partition's range to encompass this new partition, but we - * must make sure that there are no primary partitions between - * it and the closest logical drive in extended partition. - */ - if (first < ext_info.first_sector) { - if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - if (first == 0) { - ext_info.first_sector = 0; - ext_info.offset = first = offset; - } else - ext_info.first_sector = first; - } - } else if (last > ext_info.last_sector) { - if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else - ext_info.last_sector = last; - } - } - } - - if (first != p_info[i].first_sector && - !(IS_LOGICAL(num) && first == offset)) { - insert_part(i, PRI_OR_LOG, FREE_SPACE, 0, - p_info[i].first_sector, first-1, 0); - i++; - } - - if (last != p_info[i].last_sector) - insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0, - last+1, p_info[i].last_sector, 0); - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - check_part_info(); - - return 0; -} - -int find_primary(void) -{ - int num = 0, cur = 0; - - while (cur < num_parts && IS_PRIMARY(num)) - if ((p_info[cur].id > 0 && p_info[cur].num == num) || - (ext_info.id == EXTENDED && ext_info.num == num)) { - num++; - cur = 0; - } else - cur++; - - if (!IS_PRIMARY(num)) - return -1; - else - return num; -} - -int find_logical(int i) -{ - int num = -1; - int j; - - for (j = i; j < num_parts && num == -1; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - num = p_info[j].num; - - if (num == -1) { - num = 4; - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num == num) - num++; - } - - return num; -} - -void inc_logical(int i) -{ - int j; - - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -} - -void new_part(int i) -{ - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - int first = p_info[i].first_sector; - int last = p_info[i].last_sector; - int offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - int num_sects = last - first + 1; - int len, ext, j; - - if (p_info[i].num == PRI_OR_LOG) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC); - if (toupper(c) == 'P') - num = find_primary(); - else if (toupper(c) == 'L') - num = find_logical(i); - else - return; - } else if (p_info[i].num == PRIMARY) - num = find_primary(); - else if (p_info[i].num == LOGICAL) - num = find_logical(i); - else - print_warning("!!! Internal error !!!"); - - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); - if ((len = get_string(response, LINE_LENGTH, def)) <= 0 && - len != GS_DEFAULT) - return; - else if (len > 0) { -#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads))) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*1024)*sectors*heads; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } - } - - if (num_sects <= 0 || - num_sects > p_info[i].last_sector - p_info[i].first_sector + 1) - return; - - if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) { - /* Determine where inside free space to put partition. - */ - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Add partition at beginning or end of free space [be]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC); - if (toupper(c) == 'B') - last = first + num_sects - 1; - else if (toupper(c) == 'E') - first = last - num_sects + 1; - else - return; - } - - if (IS_LOGICAL(num) && ext_info.id != EXTENDED) { - /* We want to add a logical partition, but need to create an - * extended partition first. - */ - if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); - return; - } - (void)add_part(ext, EXTENDED, 0, first, last, - (first == 0 ? sectors : 0)); - } - - if (IS_LOGICAL(num)) - inc_logical(i); - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - (void)add_part(num, id, flags, first, last, offset); -} - -void clear_p_info(void) -{ - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = sectors*heads*cylinders - 1; - p_info[0].offset = 0; - p_info[0].flags = 0; - p_info[0].id = FREE_SPACE; - p_info[0].num = PRI_OR_LOG; - - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; -} - -void fill_p_info(void) -{ - int p, i; - struct hd_geometry geometry; - partition_table buffer; - partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; - - if ((fd = open(disk_device, O_RDWR)) < 0) - fatal(BAD_OPEN); - read_sector(buffer.c.b, 0); - - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { - if (!heads) - heads = geometry.heads; - if (!sectors) - sectors = geometry.sectors; - if (!cylinders) - cylinders = geometry.cylinders; - } - - if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); - - clear_p_info(); - - if (!zero_table) { - for (i = 0; i < 4; i++) { - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, - ((buffer.p.part[i].start_sect <= sectors) ? - 0 : buffer.p.part[i].start_sect), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, - ((buffer.p.part[i].start_sect <= sectors) ? - buffer.p.part[i].start_sect : 0))) { - fatal(BAD_PRIMARY); - } - if (buffer.p.part[i].sys_ind == EXTENDED) - tmp_ext = ext_info; - } - - if (tmp_ext.id == EXTENDED) { - ext_info = tmp_ext; - logical_sectors[logical] = ext_info.first_sector; - read_sector(buffer.c.b, logical_sectors[logical++]); - i = 4; - do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - buffer.p.part[p].sys_ind == 5); - p++); - if (p > 3) - fatal(BAD_LOGICAL); - - if (add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect)) { - fatal(BAD_LOGICAL); - } - - for (p = 0; - p < 4 && buffer.p.part[p].sys_ind != 5; - p++); - if (p < 4) { - logical_sectors[logical] = - ext_info.first_sector + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (p < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -void fill_part_table(struct partition *p, partition_info *pi) -{ - int sects; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; - else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; - sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector+pi->offset); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); -} - -void fill_primary_table(partition_table *buffer) -{ - int i; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(p_info[i].num)) - fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i])); - - if (ext_info.id == EXTENDED) - fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - - buffer->p.flag = PART_TABLE_FLAG; -} - -void fill_logical_table(partition_table *buffer, partition_info *pi) -{ - struct partition *p; - int i, sects; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) - for (i = 0; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - fill_part_table(&(buffer->p.part[0]), pi); - - for (i = 0; - i < num_parts && pi->num != p_info[i].num - 1; - i++); - - if (i < num_parts) { - p = &(buffer->p.part[1]); - pi = &(p_info[i]); - - p->boot_ind = 0; - p->sys_ind = 5; - p->start_sect = pi->first_sector - ext_info.first_sector; - p->nr_sects = pi->last_sector - pi->first_sector + 1; - sects = ((pi->first_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); - } - - buffer->p.flag = PART_TABLE_FLAG; -} - -void write_part_table(void) -{ - int i, done = FALSE, len; - partition_table buffer; - char response[LINE_LENGTH]; - - print_warning(WRITE_WARN); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table to disk? (yes or no): "); - - len = get_string(response, LINE_LENGTH, NULL); - - clear_warning(); - - if (len == GS_ESCAPE) - return; - else if (len == 2 && - toupper(response[0]) == 'N' && - toupper(response[1]) == 'O') { - print_warning(NO_WRITE); - return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') - done = TRUE; - else - print_warning(YES_NO); - } - - clear_warning(); - print_warning(WRITING_PART); - refresh(); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - write_sector(buffer.c.b, 0); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - /* Read the extended partition table from disk ??? KEM */ - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - write_sector(buffer.c.b, p_info[i].first_sector); - } - - sync(); - sleep(2); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; - sync(); - sleep(4); - - clear_warning(); - if (changed) - print_warning(YES_WRITE); - else - print_warning(RRPART_FAILED); -} - -void fp_printf(FILE *fp, char *format, ...) -{ - va_list args; - char buf[1024]; - int y, x; - - va_start(args, format); - vsprintf(buf, format, args); - va_end(args); - - if (fp == NULL) { - /* The following works best if the string to be printed has at - most only one newline. */ - printw("%s", buf); - getyx(stdscr, y, x); - if (y >= COMMAND_LINE_Y-2) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - } - } else - fprintf(fp, "%s", buf); -} - -#define MAX_PER_LINE 16 -void print_file_buffer(FILE *fp, char *buffer) -{ - int i,l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - fp_printf(fp, "0x%03X:", i); - fp_printf(fp, " %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - fp_printf(fp, "\n"); - l = -1; - } - } - if (l > 0) - fp_printf(fp, "\n"); - fp_printf(fp, "\n"); -} - -void print_raw_table(void) -{ - int i, to_file; - partition_table buffer; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Disk Drive: %s\n", disk_device); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - print_file_buffer(fp, buffer.c.b); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - print_file_buffer(fp, buffer.c.b); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_p_info_entry(FILE *fp, partition_info *p) -{ - int size; - char part_str[21]; - - if (p->id == UNUSABLE) - fp_printf(fp, " None "); - else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); - else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); - else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); - else - fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%6d%c", p->offset, - ((((p->first_sector == 0 || IS_LOGICAL(p->num)) && - (p->offset != sectors)) || - (p->first_sector != 0 && IS_PRIMARY(p->num) && - p->offset != 0)) ? - '#' : ' ')); - - fp_printf(fp, " "); - - size = p->last_sector - p->first_sector + 1; - fp_printf(fp, "%7d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - if (p->id == UNUSABLE) - sprintf(part_str, "%.16s", "Unusable"); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.16s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id); - else - sprintf(part_str, "%.16s (%02X)", "Unknown", p->id); - fp_printf(fp, "%-21.21s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); - else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); - else - fp_printf(fp, "None (%02X)", p->flags); - - fp_printf(fp, "\n"); -} - -void print_p_info(void) -{ - char fname[LINE_LENGTH]; - FILE *fp; - int i, to_file, pext = (ext_info.id == EXTENDED); - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " First Last\n"); - fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n"); - fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n"); - - for (i = 0; i < num_parts; i++) { - if (pext && (p_info[i].first_sector >= ext_info.first_sector)) { - print_p_info_entry(fp,&ext_info); - pext = FALSE; - } - print_p_info_entry(fp, &(p_info[i])); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_part_entry(FILE *fp, int num, partition_info *pi) -{ - int first = 0, start = 0, end = 0, size = 0; - int ss = 0, sh = 0, sc = 0; - int es = 0, eh = 0, ec = 0; - int flags = 0, id = 0; - - if (pi != NULL) { - flags = pi->flags; - id = pi->id; - - if (IS_LOGICAL(num)) - first = pi->offset; - else - first = pi->first_sector + pi->offset; - - start = pi->first_sector + pi->offset; - end = pi->last_sector; - size = end - start + 1; - if ((start/(sectors*heads)) > 1023) - start = heads*sectors*1024 - 1; - if ((end/(sectors*heads)) > 1023) - end = heads*sectors*1024 - 1; - - ss = start % sectors + 1; - start /= sectors; - sh = start % heads; - sc = start / heads; - - es = end % sectors + 1; - end /= sectors; - eh = end % heads; - ec = end / heads; - } - - fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n", - num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); -} - - -void print_part_table(void) -{ - int i, j, to_file; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n"); - - for (i = 0; i < 4; i++) { - for (j = 0; - j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i); - j++); - if (j < num_parts) { - print_part_entry(fp, i, &(p_info[j])); - } else if (ext_info.id == EXTENDED && ext_info.num == i) { - print_part_entry(fp, i, &ext_info); - } else { - print_part_entry(fp, i, NULL); - } - } - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) - print_part_entry(fp, p_info[i].num, &(p_info[i])); - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_tables(void) -{ - int done = FALSE; - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: "); - clrtoeol(); - refresh(); - - while (!done) - switch (toupper(getch())) { - case 'R': - print_raw_table(); - done = TRUE; - break; - case 'S': - print_p_info(); - done = TRUE; - break; - case 'T': - print_part_table(); - done = TRUE; - break; - case ESC: - done = TRUE; - break; - } -} - -#define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" -void display_help() -{ - char *help_text[] = { - "Help Screen for cfdisk " VERSION, - "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", - "", - "Copyright (C) 1994 Kevin E. Martin", - "", - "Command Meaning", - "------- -------", - " b Toggle bootable flag of the current partition", - " d Delete the current partition", - " g Change cylinders, heads, sectors-per-track parameters", - " WARNING: This option should only be used by people who", - " know what they are doing.", - " h Print this screen", - " m Maximize disk usage of the current partition", - " Note: This may make the partition incompatible with", - " DOS, OS/2, ...", - " n Create new partition from free space", - " p Print partition table to the screen or to a file", - " There are several different formats for the partition", - " that you can choose from:", - " r - Raw data (exactly what would be written to disk)", - " s - Table ordered by sectors", - " t - Table in raw format", - " q Quit program without writing partition table", - " t Change the filesystem type", - " u Change units of the partition size display", - " Rotates through Mb, sectors and cylinders", - " W Write partition table to disk (must enter upper case W)", - " Since this might destroy data on the disk, you must", - " either confirm or deny the write by entering `yes' or", - " `no'", - "Up Arrow Move cursor to the previous partition", - "Down Arrow Move cursor to the next partition", - "CTRL-L Redraws the screen", - " ? Print this screen", - "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", - END_OF_HELP - }; - - int cur_line = 0; - FILE *fp = NULL; - - erase(); - move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); -} - -int change_geometry(void) -{ - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - int tmp_val; - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Change disk geometry information [chs]: "); - clrtoeol(); - refresh(); - - clear_warning(); - - switch (toupper(getch())) { - case 'C': - sprintf(def, "%d", cylinders); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_CYLINDERS); - } - break; - case 'H': - sprintf(def, "%d", heads); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - heads = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_HEADS); - } - break; - case 'S': - sprintf(def, "%d", sectors); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_SECTORS); - } - break; - case ESC: - case CR: - done = TRUE; - break; - default: - putchar(BELL); - break; - } - } - - if (ret_val) { - if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) { - while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) - remove_part(num_parts-1); - else - del_part(num_parts-1); - } - - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - - if (ext_info.last_sector > heads*sectors*cylinders-1) - ext_info.last_sector = heads*sectors*cylinders - 1; - } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) { - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - } else { - insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0, - p_info[num_parts-1].last_sector+1, - heads*sectors*cylinders-1, 0); - } - } - - /* Make sure the partitions are correct */ - check_part_info(); - } - - return ret_val; -} - -void change_id(int i) -{ - char id[LINE_LENGTH], def[LINE_LENGTH]; - int num_types = 0; - int num_across, num_down; - int len, new_id = LINUX; - int y_start, y_end; - int j, pos; - - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; - - num_across = COLS/COL_ID_WIDTH; - num_down = (((float)num_types)/num_across + 1); - y_start = COMMAND_LINE_Y - 1 - num_down; - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - - for (pos = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) { - move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-16.16s", j, partition_type[j]); - pos++; - } - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); - if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) - return; - - if (len != GS_DEFAULT) { - if (!isxdigit(id[0])) - return; - new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) - if (isxdigit(id[1])) - new_id = new_id*16 + - (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); - else - return; - } - - if (new_id == 0) - print_warning(ID_EMPTY); - else if (new_id == EXTENDED) - print_warning(ID_EXT); - else - p_info[i].id = new_id; -} - -void draw_partition(int i) -{ - int size, j; - int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - - if (!arrow_cursor) { - move(y, 0); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - mvprintw(y, NAME_START, - "%s%d", disk_device, p_info[i].num+1); - if (p_info[i].flags) { - if (p_info[i].flags == ACTIVE_FLAG) - mvaddstr(y, FLAGS_START, "Boot"); - else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - addstr(", NC"); - } else { - if (p_info[i].offset != 0) - addstr(", NC"); - } - } else { - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - mvaddstr(y, FLAGS_START, "NC"); - } else { - if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); - } - } - } - mvaddstr(y, PTYPE_START, - (p_info[i].id == UNUSABLE ? "" : - (IS_LOGICAL(p_info[i].num) ? "Logical" : - (p_info[i].num >= 0 ? "Primary" : - (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : - (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - if (p_info[i].id == UNUSABLE) - mvaddstr(y, FSTYPE_START, "Unusable"); - else if (p_info[i].id == FREE_SPACE) - mvaddstr(y, FSTYPE_START, "Free Space"); - else if (partition_type[p_info[i].id]) - mvaddstr(y, FSTYPE_START, partition_type[p_info[i].id]); - else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - - size = p_info[i].last_sector - p_info[i].first_sector + 1; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%9d", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%9d", size/(sectors*heads)); - else - mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100); - if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) || - ((p_info[i].first_sector/(sectors*heads)) != - ceiling(p_info[i].first_sector/(sectors*heads)))) - mvprintw(y, COLUMNS-1, "*"); -} - -void init_const(void) -{ - if (!defined) { - NAME_START = (((float)NAME_START)/COLUMNS)*COLS; - FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS; - PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS; - FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS; - SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS; - COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS; - - COMMAND_LINE_Y = LINES - 4; - WARNING_START = LINES - 2; - - if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0) - NUM_ON_SCREEN = 1; - - COLUMNS = COLS; - defined = TRUE; - } -} - -void draw_screen(void) -{ - int i; - char *line; - - line = (char *)malloc((COLS+1)*sizeof(char)); - - if (warning_last_time) { - for (i = 0; i < COLS; i++) { - move(WARNING_START, i); - line[i] = inch(); - } - line[COLS] = 0; - } - - erase(); - - if (warning_last_time) - mvaddstr(WARNING_START, 0, line); - - - sprintf(line, "cfdisk %s", VERSION); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d", - heads, sectors, cylinders); - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - - mvaddstr(DISK_TABLE_START, NAME_START, "Name"); - mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors"); - else if (display_units == CYLINDERS) - mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders"); - else - mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)"); - - move(DISK_TABLE_START+1, 1); - for (i = 1; i < COLS-1; i++) - addch('-'); - - if (NUM_ON_SCREEN >= num_parts) - for (i = 0; i < num_parts; i++) - draw_partition(i); - else - for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN && - i < num_parts; - i++) - draw_partition(i); - - free(line); -} - -int draw_cursor(int move) -{ - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) - return -1; - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " "); - else - draw_partition(cur_part); - - cur_part += move; - - if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN != - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN) - draw_screen(); - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->"); - else { - standout(); - draw_partition(cur_part); - standend(); - } - - return 0; -} - -void die(int dummy) -{ - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void do_curses_fdisk(void) -{ - int done = FALSE; - char command; - - initscr(); - old_SIGINT = signal(SIGINT, die); - old_SIGTERM = signal(SIGTERM, die); -#ifdef DEBUG - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#endif - - cbreak(); - noecho(); - nonl(); - - init_const(); - - fill_p_info(); - - draw_screen(); - - while (!done) { - (void)draw_cursor(0); - - if (p_info[cur_part].id == FREE_SPACE) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: "); - else if (p_info[cur_part].id > 0) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: "); - else - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: "); - - clrtoeol(); - refresh(); - - clear_warning(); - - switch (command = getch()) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(NO_FLAGS); - break; - case 'D': - case 'd': - if (p_info[cur_part].id > 0) { - del_part(cur_part); - if (cur_part >= num_parts) - cur_part = num_parts - 1; - draw_screen(); - } else - print_warning(DEL_EMPTY); - break; - case 'G': - case 'g': - if (change_geometry()) - draw_screen(); - break; - case 'M': - case 'm': - if (p_info[cur_part].id > 0) { - if (p_info[cur_part].first_sector == 0 || - IS_LOGICAL(p_info[cur_part].num)) { - if (p_info[cur_part].offset == sectors) - p_info[cur_part].offset = 1; - else - p_info[cur_part].offset = sectors; - draw_screen(); - } else if (p_info[cur_part].offset != 0) - p_info[cur_part].offset = 0; - else - print_warning(MAX_UNMAXABLE); - } else - print_warning(MAX_UNMAXABLE); - break; - case 'N': - case 'n': - if (p_info[cur_part].id == FREE_SPACE) { - new_part(cur_part); - draw_screen(); - } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); - else - print_warning(ADD_EXISTS); - break; - case 'P': - case 'p': - print_tables(); - draw_screen(); - break; - case 'Q': - case 'q': - done = TRUE; - break; - case 'T': - case 't': - if (p_info[cur_part].id > 0) { - change_id(cur_part); - draw_screen(); - } else - print_warning(TYPE_EMPTY); - break; - case 'U': - case 'u': - if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case ESC: - if ((command = getch()) == '[') { - command = getch(); - switch (command) { - case 'A' : /* Up arrow */ - if (!draw_cursor(-1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'B' : /* Down arrow */ - if (!draw_cursor(1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'C' : /* Right arrow */ - case 'D' : /* Left arrow */ - } - } - if (command) - putchar(BELL); /* CTRL-G */ - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - default: - print_warning(BAD_COMMAND); - putchar(BELL); /* CTRL-G */ - } - } - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void copyright(void) -{ - fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n"); -} - -void usage(char *prog_name) -{ - fprintf(stderr, - "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n", - prog_name); - fprintf(stderr, - "[ -P opt ] device\n"); - copyright(); -} - -void main(int argc, char **argv) -{ - char c; - int i, len; - - while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) - switch (c) { - case 'a': - arrow_cursor = TRUE; - break; - case 'c': - cylinders = atoi(optarg); - if (cylinders <= 0 || cylinders > MAX_CYLINDERS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS); - exit(1); - } - break; - case 'h': - heads = atoi(optarg); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); - exit(1); - } - break; - case 's': - sectors = atoi(optarg); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk %s\n", VERSION); - copyright(); - exit(0); - case 'z': - zero_table = TRUE; - break; - case 'P': - len = strlen(optarg); - for (i = 0; i < len; i++) { - switch (optarg[i]) { - case 'r': - print_only |= PRINT_RAW_TABLE; - break; - case 's': - print_only |= PRINT_SECTOR_TABLE; - break; - case 't': - print_only |= PRINT_PARTITION_TABLE; - break; - default: - usage(argv[0]); - break; - } - } - break; - default: - usage(argv[0]); - exit(1); - } - - if (argc-optind == 1) - disk_device = argv[optind]; - else if (argc-optind != 0) { - usage(argv[0]); - exit(1); - } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - - if (print_only) { - fill_p_info(); - if (print_only & PRINT_RAW_TABLE) - print_raw_table(); - if (print_only & PRINT_SECTOR_TABLE) - print_p_info(); - if (print_only & PRINT_PARTITION_TABLE) - print_part_table(); - } else - do_curses_fdisk(); -} diff --git a/disk-utils/cfdisk.c.orig b/disk-utils/cfdisk.c.orig deleted file mode 100644 index 3b9f22f5..00000000 --- a/disk-utils/cfdisk.c.orig +++ /dev/null @@ -1,2066 +0,0 @@ -/**************************************************************************** - * - * CFDISK - * - * cfdisk is a curses based disk drive partitioning program that can - * create partitions for a wide variety of operating systems including - * Linux, MS-DOS and OS/2. - * - * cfdisk was inspired by the fdisk program, by A. V. Le Blanc - * (LeBlanc@mcc.ac.uk). - * - * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - * - * cfdisk 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 2 of the License, or - * (at your option) any later version. - * - * cfdisk is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with cfdisk; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for BLKRRPART */ - -typedef long ext2_loff_t; -extern ext2_loff_t ext2_llseek(unsigned int fd, - ext2_loff_t offset, - unsigned int origin); - -#define VERSION "0.8 BETA (>2GB)" - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_CYLINDERS 65535 -#define MAX_HEADS 255 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 - -#define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define EXTENDED 0x05 -#define LINUX_MINIX 0x81 -#define LINUX_SWAP 0x82 -#define LINUX 0x83 - -#define ADD_EXISTS "This partition is already in use" -#define ADD_UNUSABLE "This partition is unusable" -#define DEL_EMPTY "Cannot delete an empty partition" -#define ID_EMPTY "Cannot change FS Type to empty" -#define ID_EXT "Cannot change FS Type to extended" -#define NEED_EXT "No room to create the extended partition" -#define NO_FLAGS "Cannot make this partition bootable" -#define NO_MORE_PARTS "No more partitions" -#define PRINT_OPEN_ERR "Cannot open file '%s'" -#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions" -#define TYPE_EMPTY "Cannot change the type of an empty partition" -#define BAD_COMMAND "Illegal command" -#define MAX_UNMAXABLE "Cannot maximize this partition" -#define BAD_OPEN "Cannot open disk drive" -#define BAD_SEEK "Cannot seek on disk drive" -#define BAD_READ "Cannot read disk drive" -#define BAD_WRITE "Cannot write disk drive" -#define BAD_GEOMETRY "Cannot read disk drive geometry" -#define BAD_PRIMARY "Bad primary partition" -#define BAD_LOGICAL "Bad logical partition" -#define BAD_CYLINDERS "Illegal cylinders value" -#define BAD_HEADS "Illegal heads value" -#define BAD_SECTORS "Illegal sectors value" -#define WRITE_WARN "Warning!! This may destroy data on your disk!" -#define YES_NO "Please enter `yes' or `no'" -#define WRITING_PART "Writing partition table to disk..." -#define YES_WRITE "Wrote partition table to disk" -#define NO_WRITE "Did not write partition table to disk" -#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." - -#define PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 20 - -#define CR '\015' -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' - -/* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 - -#define GS_DEFAULT -1 -#define GS_ESCAPE -2 - -#define PRINT_RAW_TABLE 1 -#define PRINT_SECTOR_TABLE 2 -#define PRINT_PARTITION_TABLE 4 - -#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4) -#define IS_LOGICAL(p) ((p) > 3) - -#define round_int(d) ((double)((int)(d+0.5))) -#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d))) - -#define set_hsc(h,s,c,sector) \ -{ \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xFF; \ - s |= (sector >> 2) & 0xC0;\ -} - -#define ALIGNMENT 2 -typedef union { - struct { - unsigned char align[ALIGNMENT]; - unsigned char b[SECTOR_SIZE]; - } c; - struct { - unsigned char align[ALIGNMENT]; - unsigned char buffer[0x1BE]; - struct partition part[4]; - unsigned short flag; - } p; -} partition_table; - -typedef struct { - int first_sector; /* first sector in partition */ - int last_sector; /* last sector in partition */ - int offset; /* offset from first sector to start of data */ - int flags; /* active == 0x80 */ - int id; /* filesystem type */ - int num; /* number of partition -- primary vs. logical */ -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; -int changed = FALSE; -int opened = FALSE; - -partition_info p_info[MAXIMUM_PARTS]; -partition_info ext_info; -int num_parts = 0; - -int logical = 0; -int logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int print_only = 0; - -/* Curses screen information */ -int cur_part = 0; -int warning_last_time = FALSE; -int defined = FALSE; -int COLUMNS = 80; -int NUM_ON_SCREEN = 1; - -/* Y coordinates */ -int HEADER_START = 0; -int DISK_TABLE_START = 5; -int WARNING_START = 23; -int COMMAND_LINE_Y = 21; - -/* X coordinates */ -int NAME_START = 4; -int FLAGS_START = 16; -int PTYPE_START = 30; -int FSTYPE_START = 45; -int SIZE_START = 70; -int COMMAND_LINE_X = 5; - -#define NUM_PART_TYPES 256 -char *partition_type[NUM_PART_TYPES] = { - [LINUX_MINIX] = "Linux/MINIX", - [LINUX_SWAP] = "Linux Swap", - [LINUX] = "Linux", - [FREE_SPACE] = "Free Space", - [EXTENDED] = "Extended", - [0x01] = "DOS 12-bit FAT", - [0x04] = "DOS 16-bit < 32Mb", - [0x06] = "DOS 16-bit >=32Mb", - [0x07] = "OS/2 HPFS", - [0x0A] = "OS/2 Boot Manager", - [0xA5] = "BSD/386", - -/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk) - * fdisk program. I do not know where they came from, but I include - * them for completeness. - */ - - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x40] = "Venix 80286", - [0x51] = "Novell?", - [0x52] = "Microport", - [0x63] = "GNU HURD", - [0x64] = "Novell", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xF2] = "DOS secondary", - [0xFF] = "BBT" -}; - -void fdexit(int ret) -{ - if (opened) - close(fd); - - if (changed) { - fprintf(stderr, "Disk has been changed.\n"); - fprintf(stderr, "Reboot the system to ensure the partition " - "table is correctly updated.\n"); - - fprintf( stderr, "\nWARNING: If you have created or modified any\n" - "DOS 6.x partitions, please see the cfdisk manual\n" - "page for additional information.\n" ); - } - - - exit(ret); -} - -int get_string(char *str, int len, char *def) -{ - char c; - int i = 0; - int x, y; - int use_def = FALSE; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - while ((c = getch()) != '\n' && c != CR) { - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: - if (i < len && isprint(c)) { - mvaddch(y, x+i, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - } else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -void clear_warning(void) -{ - int i; - - if (!warning_last_time) - return; - - move(WARNING_START,0); - for (i = 0; i < COLS; i++) - addch(' '); - - warning_last_time = FALSE; -} - -void print_warning(char *s) -{ - mvaddstr(WARNING_START, (COLS-strlen(s))/2, s); - putchar(BELL); /* CTRL-G */ - - warning_last_time = TRUE; -} - -void fatal(char *s) -{ - char str[LINE_LENGTH]; - - sprintf(str, "FATAL ERROR: %s", s); - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - - refresh(); - - (void)getch(); - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(1); -} - -void read_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); -} - -void write_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); -} - -void check_part_info(void) -{ - int i, pri = 0, log = 0; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED) - if (log > 0) - pri++; - else { - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; - } - - if (pri >= 4) - for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else - p_info[i].id = UNUSABLE; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - else /* if (pri < 4) */ - for (i = 0; i < num_parts; i++) { - if (p_info[i].id == UNUSABLE) - p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) - p_info[i].num = LOGICAL; - else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else - p_info[i].num = PRIMARY; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } -} - -void remove_part(int i) -{ - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; -} - -void insert_part(int i, int num, int id, int flags, int first, int last, - int offset) -{ - int p; - - for (p = num_parts; p > i; p--) - p_info[p] = p_info[p-1]; - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - num_parts++; -} - -void del_part(int i) -{ - int num = p_info[i].num; - - if (i > 0 && (p_info[i-1].id == FREE_SPACE || - p_info[i-1].id == UNUSABLE)) { - /* Merge with previous partition */ - p_info[i-1].last_sector = p_info[i].last_sector; - remove_part(i--); - } - - if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE || - p_info[i+1].id == UNUSABLE)) { - /* Merge with next partition */ - p_info[i+1].first_sector = p_info[i].first_sector; - remove_part(i); - } - - if (i > 0) - p_info[i].first_sector = p_info[i-1].last_sector + 1; - else - p_info[i].first_sector = 0; - - if (i < num_parts - 1) - p_info[i].last_sector = p_info[i+1].first_sector - 1; - else - p_info[i].last_sector = sectors*heads*cylinders - 1; - - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - - if (IS_LOGICAL(num)) { - /* We have a logical partition --> shrink the extended partition - * if (1) this is the first logical drive, or (2) this is the - * last logical drive; and if there are any other logical drives - * then renumber the ones after "num". - */ - if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) - ext_info.first_sector = p_info[i].last_sector + 1; - if (i == num_parts-1 || - (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num))) - ext_info.last_sector = p_info[i].first_sector - 1; - for (i = 0; i < num_parts; i++) - if (p_info[i].num > num) - p_info[i].num--; - } - - /* Clean up the rest of the partitions */ - check_part_info(); -} - -int add_part(int num, int id, int flags, int first, int last, int offset) -{ - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS || - first < 0 || - first >= cylinders*heads*sectors || - last < 0 || - last >= cylinders*heads*sectors) - return -1; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED && log > 0) - pri++; - - if (IS_PRIMARY(num)) - if (pri >= 4) - return -1; - else - pri++; - - for (i = 0; p_info[i].last_sector < first; i++); - - if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector) - return -1; - - if (id == EXTENDED) - if (ext_info.id != FREE_SPACE) - return -1; - else if (IS_PRIMARY(num)) { - ext_info.first_sector = first; - ext_info.last_sector = last; - ext_info.offset = offset; - ext_info.flags = flags; - ext_info.id = EXTENDED; - ext_info.num = num; - - return 0; - } else - return -1; - - if (IS_LOGICAL(num)) { - if (ext_info.id != EXTENDED) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); - } else { - /* We might have a logical partition outside of the extended - * partition's range --> we have to extend the extended - * partition's range to encompass this new partition, but we - * must make sure that there are no primary partitions between - * it and the closest logical drive in extended partition. - */ - if (first < ext_info.first_sector) { - if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - if (first == 0) { - ext_info.first_sector = 0; - ext_info.offset = first = offset; - } else - ext_info.first_sector = first; - } - } else if (last > ext_info.last_sector) { - if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else - ext_info.last_sector = last; - } - } - } - - if (first != p_info[i].first_sector && - !(IS_LOGICAL(num) && first == offset)) { - insert_part(i, PRI_OR_LOG, FREE_SPACE, 0, - p_info[i].first_sector, first-1, 0); - i++; - } - - if (last != p_info[i].last_sector) - insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0, - last+1, p_info[i].last_sector, 0); - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - check_part_info(); - - return 0; -} - -int find_primary(void) -{ - int num = 0, cur = 0; - - while (cur < num_parts && IS_PRIMARY(num)) - if ((p_info[cur].id > 0 && p_info[cur].num == num) || - (ext_info.id == EXTENDED && ext_info.num == num)) { - num++; - cur = 0; - } else - cur++; - - if (!IS_PRIMARY(num)) - return -1; - else - return num; -} - -int find_logical(int i) -{ - int num = -1; - int j; - - for (j = i; j < num_parts && num == -1; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - num = p_info[j].num; - - if (num == -1) { - num = 4; - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num == num) - num++; - } - - return num; -} - -void inc_logical(int i) -{ - int j; - - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -} - -void new_part(int i) -{ - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - int first = p_info[i].first_sector; - int last = p_info[i].last_sector; - int offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - int num_sects = last - first + 1; - int len, ext, j; - - if (p_info[i].num == PRI_OR_LOG) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC); - if (toupper(c) == 'P') - num = find_primary(); - else if (toupper(c) == 'L') - num = find_logical(i); - else - return; - } else if (p_info[i].num == PRIMARY) - num = find_primary(); - else if (p_info[i].num == LOGICAL) - num = find_logical(i); - else - print_warning("!!! Internal error !!!"); - - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); - if ((len = get_string(response, LINE_LENGTH, def)) <= 0 && - len != GS_DEFAULT) - return; - else if (len > 0) { -#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads))) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*1024)*sectors*heads; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } - } - - if (num_sects <= 0 || - num_sects > p_info[i].last_sector - p_info[i].first_sector + 1) - return; - - if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) { - /* Determine where inside free space to put partition. - */ - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Add partition at beginning or end of free space [be]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC); - if (toupper(c) == 'B') - last = first + num_sects - 1; - else if (toupper(c) == 'E') - first = last - num_sects + 1; - else - return; - } - - if (IS_LOGICAL(num) && ext_info.id != EXTENDED) { - /* We want to add a logical partition, but need to create an - * extended partition first. - */ - if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); - return; - } - (void)add_part(ext, EXTENDED, 0, first, last, - (first == 0 ? sectors : 0)); - } - - if (IS_LOGICAL(num)) - inc_logical(i); - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - (void)add_part(num, id, flags, first, last, offset); -} - -void clear_p_info(void) -{ - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = sectors*heads*cylinders - 1; - p_info[0].offset = 0; - p_info[0].flags = 0; - p_info[0].id = FREE_SPACE; - p_info[0].num = PRI_OR_LOG; - - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; -} - -void fill_p_info(void) -{ - int p, i; - struct hd_geometry geometry; - partition_table buffer; - partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; - - if ((fd = open(disk_device, O_RDWR)) < 0) - fatal(BAD_OPEN); - read_sector(buffer.c.b, 0); - - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { - if (!heads) - heads = geometry.heads; - if (!sectors) - sectors = geometry.sectors; - if (!cylinders) - cylinders = geometry.cylinders; - } - - if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); - - clear_p_info(); - - if (!zero_table) { - for (i = 0; i < 4; i++) { - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, - ((buffer.p.part[i].start_sect <= sectors) ? - 0 : buffer.p.part[i].start_sect), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, - ((buffer.p.part[i].start_sect <= sectors) ? - buffer.p.part[i].start_sect : 0))) { - fatal(BAD_PRIMARY); - } - if (buffer.p.part[i].sys_ind == EXTENDED) - tmp_ext = ext_info; - } - - if (tmp_ext.id == EXTENDED) { - ext_info = tmp_ext; - logical_sectors[logical] = ext_info.first_sector; - read_sector(buffer.c.b, logical_sectors[logical++]); - i = 4; - do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - buffer.p.part[p].sys_ind == 5); - p++); - if (p > 3) - fatal(BAD_LOGICAL); - - if (add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect)) { - fatal(BAD_LOGICAL); - } - - for (p = 0; - p < 4 && buffer.p.part[p].sys_ind != 5; - p++); - if (p < 4) { - logical_sectors[logical] = - ext_info.first_sector + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (p < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -void fill_part_table(struct partition *p, partition_info *pi) -{ - int sects; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; - else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; - sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector+pi->offset); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); -} - -void fill_primary_table(partition_table *buffer) -{ - int i; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(p_info[i].num)) - fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i])); - - if (ext_info.id == EXTENDED) - fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - - buffer->p.flag = PART_TABLE_FLAG; -} - -void fill_logical_table(partition_table *buffer, partition_info *pi) -{ - struct partition *p; - int i, sects; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) - for (i = 0; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - fill_part_table(&(buffer->p.part[0]), pi); - - for (i = 0; - i < num_parts && pi->num != p_info[i].num - 1; - i++); - - if (i < num_parts) { - p = &(buffer->p.part[1]); - pi = &(p_info[i]); - - p->boot_ind = 0; - p->sys_ind = 5; - p->start_sect = pi->first_sector - ext_info.first_sector; - p->nr_sects = pi->last_sector - pi->first_sector + 1; - sects = ((pi->first_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); - } - - buffer->p.flag = PART_TABLE_FLAG; -} - -void write_part_table(void) -{ - int i, done = FALSE, len; - partition_table buffer; - char response[LINE_LENGTH]; - - print_warning(WRITE_WARN); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table to disk? (yes or no): "); - - len = get_string(response, LINE_LENGTH, NULL); - - clear_warning(); - - if (len == GS_ESCAPE) - return; - else if (len == 2 && - toupper(response[0]) == 'N' && - toupper(response[1]) == 'O') { - print_warning(NO_WRITE); - return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') - done = TRUE; - else - print_warning(YES_NO); - } - - clear_warning(); - print_warning(WRITING_PART); - refresh(); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - write_sector(buffer.c.b, 0); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - /* Read the extended partition table from disk ??? KEM */ - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - write_sector(buffer.c.b, p_info[i].first_sector); - } - - sync(); - sleep(2); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; - sync(); - sleep(4); - - clear_warning(); - if (changed) - print_warning(YES_WRITE); - else - print_warning(RRPART_FAILED); -} - -void fp_printf(FILE *fp, char *format, ...) -{ - va_list args; - char buf[1024]; - int y, x; - - va_start(args, format); - vsprintf(buf, format, args); - va_end(args); - - if (fp == NULL) { - /* The following works best if the string to be printed has at - most only one newline. */ - printw("%s", buf); - getyx(stdscr, y, x); - if (y >= COMMAND_LINE_Y-2) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - } - } else - fprintf(fp, "%s", buf); -} - -#define MAX_PER_LINE 16 -void print_file_buffer(FILE *fp, char *buffer) -{ - int i,l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - fp_printf(fp, "0x%03X:", i); - fp_printf(fp, " %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - fp_printf(fp, "\n"); - l = -1; - } - } - if (l > 0) - fp_printf(fp, "\n"); - fp_printf(fp, "\n"); -} - -void print_raw_table(void) -{ - int i, to_file; - partition_table buffer; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Disk Drive: %s\n", disk_device); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - print_file_buffer(fp, buffer.c.b); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - print_file_buffer(fp, buffer.c.b); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_p_info_entry(FILE *fp, partition_info *p) -{ - int size; - char part_str[21]; - - if (p->id == UNUSABLE) - fp_printf(fp, " None "); - else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); - else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); - else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); - else - fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%6d%c", p->offset, - ((((p->first_sector == 0 || IS_LOGICAL(p->num)) && - (p->offset != sectors)) || - (p->first_sector != 0 && IS_PRIMARY(p->num) && - p->offset != 0)) ? - '#' : ' ')); - - fp_printf(fp, " "); - - size = p->last_sector - p->first_sector + 1; - fp_printf(fp, "%7d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - if (p->id == UNUSABLE) - sprintf(part_str, "%.16s", "Unusable"); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.16s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id); - else - sprintf(part_str, "%.16s (%02X)", "Unknown", p->id); - fp_printf(fp, "%-21.21s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); - else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); - else - fp_printf(fp, "None (%02X)", p->flags); - - fp_printf(fp, "\n"); -} - -void print_p_info(void) -{ - char fname[LINE_LENGTH]; - FILE *fp; - int i, to_file, pext = (ext_info.id == EXTENDED); - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " First Last\n"); - fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n"); - fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n"); - - for (i = 0; i < num_parts; i++) { - if (pext && (p_info[i].first_sector >= ext_info.first_sector)) { - print_p_info_entry(fp,&ext_info); - pext = FALSE; - } - print_p_info_entry(fp, &(p_info[i])); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_part_entry(FILE *fp, int num, partition_info *pi) -{ - int first = 0, start = 0, end = 0, size = 0; - int ss = 0, sh = 0, sc = 0; - int es = 0, eh = 0, ec = 0; - int flags = 0, id = 0; - - if (pi != NULL) { - flags = pi->flags; - id = pi->id; - - if (IS_LOGICAL(num)) - first = pi->offset; - else - first = pi->first_sector + pi->offset; - - start = pi->first_sector + pi->offset; - end = pi->last_sector; - size = end - start + 1; - if ((start/(sectors*heads)) > 1023) - start = heads*sectors*1024 - 1; - if ((end/(sectors*heads)) > 1023) - end = heads*sectors*1024 - 1; - - ss = start % sectors + 1; - start /= sectors; - sh = start % heads; - sc = start / heads; - - es = end % sectors + 1; - end /= sectors; - eh = end % heads; - ec = end / heads; - } - - fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n", - num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); -} - - -void print_part_table(void) -{ - int i, j, to_file; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n"); - - for (i = 0; i < 4; i++) { - for (j = 0; - j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i); - j++); - if (j < num_parts) { - print_part_entry(fp, i, &(p_info[j])); - } else if (ext_info.id == EXTENDED && ext_info.num == i) { - print_part_entry(fp, i, &ext_info); - } else { - print_part_entry(fp, i, NULL); - } - } - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) - print_part_entry(fp, p_info[i].num, &(p_info[i])); - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_tables(void) -{ - int done = FALSE; - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: "); - clrtoeol(); - refresh(); - - while (!done) - switch (toupper(getch())) { - case 'R': - print_raw_table(); - done = TRUE; - break; - case 'S': - print_p_info(); - done = TRUE; - break; - case 'T': - print_part_table(); - done = TRUE; - break; - case ESC: - done = TRUE; - break; - } -} - -#define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" -void display_help() -{ - char *help_text[] = { - "Help Screen for cfdisk " VERSION, - "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", - "", - "Copyright (C) 1994 Kevin E. Martin", - "", - "Command Meaning", - "------- -------", - " b Toggle bootable flag of the current partition", - " d Delete the current partition", - " g Change cylinders, heads, sectors-per-track parameters", - " WARNING: This option should only be used by people who", - " know what they are doing.", - " h Print this screen", - " m Maximize disk usage of the current partition", - " Note: This may make the partition incompatible with", - " DOS, OS/2, ...", - " n Create new partition from free space", - " p Print partition table to the screen or to a file", - " There are several different formats for the partition", - " that you can choose from:", - " r - Raw data (exactly what would be written to disk)", - " s - Table ordered by sectors", - " t - Table in raw format", - " q Quit program without writing partition table", - " t Change the filesystem type", - " u Change units of the partition size display", - " Rotates through Mb, sectors and cylinders", - " W Write partition table to disk (must enter upper case W)", - " Since this might destroy data on the disk, you must", - " either confirm or deny the write by entering `yes' or", - " `no'", - "Up Arrow Move cursor to the previous partition", - "Down Arrow Move cursor to the next partition", - "CTRL-L Redraws the screen", - " ? Print this screen", - "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", - END_OF_HELP - }; - - int cur_line = 0; - FILE *fp = NULL; - - erase(); - move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); -} - -int change_geometry(void) -{ - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - int tmp_val; - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Change disk geometry information [chs]: "); - clrtoeol(); - refresh(); - - clear_warning(); - - switch (toupper(getch())) { - case 'C': - sprintf(def, "%d", cylinders); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_CYLINDERS); - } - break; - case 'H': - sprintf(def, "%d", heads); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - heads = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_HEADS); - } - break; - case 'S': - sprintf(def, "%d", sectors); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_SECTORS); - } - break; - case ESC: - case CR: - done = TRUE; - break; - default: - putchar(BELL); - break; - } - } - - if (ret_val) { - if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) { - while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) - remove_part(num_parts-1); - else - del_part(num_parts-1); - } - - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - - if (ext_info.last_sector > heads*sectors*cylinders-1) - ext_info.last_sector = heads*sectors*cylinders - 1; - } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) { - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - } else { - insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0, - p_info[num_parts-1].last_sector+1, - heads*sectors*cylinders-1, 0); - } - } - - /* Make sure the partitions are correct */ - check_part_info(); - } - - return ret_val; -} - -void change_id(int i) -{ - char id[LINE_LENGTH], def[LINE_LENGTH]; - int num_types = 0; - int num_across, num_down; - int len, new_id = LINUX; - int y_start, y_end; - int j, pos; - - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; - - num_across = COLS/COL_ID_WIDTH; - num_down = (((float)num_types)/num_across + 1); - y_start = COMMAND_LINE_Y - 1 - num_down; - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - - for (pos = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) { - move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-16.16s", j, partition_type[j]); - pos++; - } - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); - if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) - return; - - if (len != GS_DEFAULT) { - if (!isxdigit(id[0])) - return; - new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) - if (isxdigit(id[1])) - new_id = new_id*16 + - (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); - else - return; - } - - if (new_id == 0) - print_warning(ID_EMPTY); - else if (new_id == EXTENDED) - print_warning(ID_EXT); - else - p_info[i].id = new_id; -} - -void draw_partition(int i) -{ - int size, j; - int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - - if (!arrow_cursor) { - move(y, 0); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - mvprintw(y, NAME_START, - "%s%d", disk_device, p_info[i].num+1); - if (p_info[i].flags) { - if (p_info[i].flags == ACTIVE_FLAG) - mvaddstr(y, FLAGS_START, "Boot"); - else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - addstr(", NC"); - } else { - if (p_info[i].offset != 0) - addstr(", NC"); - } - } else { - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - mvaddstr(y, FLAGS_START, "NC"); - } else { - if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); - } - } - } - mvaddstr(y, PTYPE_START, - (p_info[i].id == UNUSABLE ? "" : - (IS_LOGICAL(p_info[i].num) ? "Logical" : - (p_info[i].num >= 0 ? "Primary" : - (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : - (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - if (p_info[i].id == UNUSABLE) - mvaddstr(y, FSTYPE_START, "Unusable"); - else if (p_info[i].id == FREE_SPACE) - mvaddstr(y, FSTYPE_START, "Free Space"); - else if (partition_type[p_info[i].id]) - mvaddstr(y, FSTYPE_START, partition_type[p_info[i].id]); - else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - - size = p_info[i].last_sector - p_info[i].first_sector + 1; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%9d", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%9d", size/(sectors*heads)); - else - mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100); - if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) || - ((p_info[i].first_sector/(sectors*heads)) != - ceiling(p_info[i].first_sector/(sectors*heads)))) - mvprintw(y, COLUMNS-1, "*"); -} - -void init_const(void) -{ - if (!defined) { - NAME_START = (((float)NAME_START)/COLUMNS)*COLS; - FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS; - PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS; - FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS; - SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS; - COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS; - - COMMAND_LINE_Y = LINES - 4; - WARNING_START = LINES - 2; - - if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0) - NUM_ON_SCREEN = 1; - - COLUMNS = COLS; - defined = TRUE; - } -} - -void draw_screen(void) -{ - int i; - char *line; - - line = (char *)malloc((COLS+1)*sizeof(char)); - - if (warning_last_time) { - for (i = 0; i < COLS; i++) { - move(WARNING_START, i); - line[i] = inch(); - } - line[COLS] = 0; - } - - erase(); - - if (warning_last_time) - mvaddstr(WARNING_START, 0, line); - - - sprintf(line, "cfdisk %s", VERSION); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d", - heads, sectors, cylinders); - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - - mvaddstr(DISK_TABLE_START, NAME_START, "Name"); - mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors"); - else if (display_units == CYLINDERS) - mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders"); - else - mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)"); - - move(DISK_TABLE_START+1, 1); - for (i = 1; i < COLS-1; i++) - addch('-'); - - if (NUM_ON_SCREEN >= num_parts) - for (i = 0; i < num_parts; i++) - draw_partition(i); - else - for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN && - i < num_parts; - i++) - draw_partition(i); - - free(line); -} - -int draw_cursor(int move) -{ - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) - return -1; - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " "); - else - draw_partition(cur_part); - - cur_part += move; - - if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN != - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN) - draw_screen(); - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->"); - else { - standout(); - draw_partition(cur_part); - standend(); - } - - return 0; -} - -void die(int dummy) -{ - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void do_curses_fdisk(void) -{ - int done = FALSE; - char command; - - initscr(); - old_SIGINT = signal(SIGINT, die); - old_SIGTERM = signal(SIGTERM, die); -#ifdef DEBUG - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#endif - - cbreak(); - noecho(); - nonl(); - - init_const(); - - fill_p_info(); - - draw_screen(); - - while (!done) { - (void)draw_cursor(0); - - if (p_info[cur_part].id == FREE_SPACE) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: "); - else if (p_info[cur_part].id > 0) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: "); - else - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: "); - - clrtoeol(); - refresh(); - - clear_warning(); - - switch (command = getch()) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(NO_FLAGS); - break; - case 'D': - case 'd': - if (p_info[cur_part].id > 0) { - del_part(cur_part); - if (cur_part >= num_parts) - cur_part = num_parts - 1; - draw_screen(); - } else - print_warning(DEL_EMPTY); - break; - case 'G': - case 'g': - if (change_geometry()) - draw_screen(); - break; - case 'M': - case 'm': - if (p_info[cur_part].id > 0) { - if (p_info[cur_part].first_sector == 0 || - IS_LOGICAL(p_info[cur_part].num)) { - if (p_info[cur_part].offset == sectors) - p_info[cur_part].offset = 1; - else - p_info[cur_part].offset = sectors; - draw_screen(); - } else if (p_info[cur_part].offset != 0) - p_info[cur_part].offset = 0; - else - print_warning(MAX_UNMAXABLE); - } else - print_warning(MAX_UNMAXABLE); - break; - case 'N': - case 'n': - if (p_info[cur_part].id == FREE_SPACE) { - new_part(cur_part); - draw_screen(); - } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); - else - print_warning(ADD_EXISTS); - break; - case 'P': - case 'p': - print_tables(); - draw_screen(); - break; - case 'Q': - case 'q': - done = TRUE; - break; - case 'T': - case 't': - if (p_info[cur_part].id > 0) { - change_id(cur_part); - draw_screen(); - } else - print_warning(TYPE_EMPTY); - break; - case 'U': - case 'u': - if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case ESC: - if ((command = getch()) == '[') { - command = getch(); - switch (command) { - case 'A' : /* Up arrow */ - if (!draw_cursor(-1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'B' : /* Down arrow */ - if (!draw_cursor(1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'C' : /* Right arrow */ - case 'D' : /* Left arrow */ - } - } - if (command) - putchar(BELL); /* CTRL-G */ - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - default: - print_warning(BAD_COMMAND); - putchar(BELL); /* CTRL-G */ - } - } - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void copyright(void) -{ - fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n"); -} - -void usage(char *prog_name) -{ - fprintf(stderr, - "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n", - prog_name); - fprintf(stderr, - "[ -P opt ] device\n"); - copyright(); -} - -void main(int argc, char **argv) -{ - char c; - int i, len; - - while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) - switch (c) { - case 'a': - arrow_cursor = TRUE; - break; - case 'c': - cylinders = atoi(optarg); - if (cylinders <= 0 || cylinders > MAX_CYLINDERS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS); - exit(1); - } - break; - case 'h': - heads = atoi(optarg); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); - exit(1); - } - break; - case 's': - sectors = atoi(optarg); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk %s\n", VERSION); - copyright(); - exit(0); - case 'z': - zero_table = TRUE; - break; - case 'P': - len = strlen(optarg); - for (i = 0; i < len; i++) { - switch (optarg[i]) { - case 'r': - print_only |= PRINT_RAW_TABLE; - break; - case 's': - print_only |= PRINT_SECTOR_TABLE; - break; - case 't': - print_only |= PRINT_PARTITION_TABLE; - break; - default: - usage(argv[0]); - break; - } - } - break; - default: - usage(argv[0]); - exit(1); - } - - if (argc-optind == 1) - disk_device = argv[optind]; - else if (argc-optind != 0) { - usage(argv[0]); - exit(1); - } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - - if (print_only) { - fill_p_info(); - if (print_only & PRINT_RAW_TABLE) - print_raw_table(); - if (print_only & PRINT_SECTOR_TABLE) - print_p_info(); - if (print_only & PRINT_PARTITION_TABLE) - print_part_table(); - } else - do_curses_fdisk(); -} diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c index 46b9e232..7f792c5c 100644 --- a/disk-utils/fdformat.c +++ b/disk-utils/fdformat.c @@ -56,9 +56,19 @@ static void verify_disk(char *name) fflush(stdout); if ((fd = open(name,O_RDONLY)) < 0) PERROR(name); for (cyl = 0; cyl < param.track; cyl++) { + int read_bytes; + printf("%3d\b\b\b",cyl); fflush(stdout); - if (read(fd,data,cyl_size) != cyl_size) PERROR("read"); + read_bytes = read(fd,data,cyl_size); + if(read_bytes != cyl_size) { + if(read_bytes < 0) + perror("Read: "); + fprintf(stderr, + "Problem reading cylinder %d, expected %d, read %d\n", + cyl, cyl_size, read_bytes); + exit(1); + } for (count = 0; count < cyl_size; count++) if (data[count] != FD_FILL_BYTE) { printf("bad data in cyl %d\nContinuing ... ",cyl); diff --git a/disk-utils/fdprm b/disk-utils/fdprm index 2a59da01..a9282e1e 100644 --- a/disk-utils/fdprm +++ b/disk-utils/fdprm @@ -24,3 +24,5 @@ 1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ????? # Add user-specific formats here +cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E +800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E diff --git a/disk-utils/frag.8 b/disk-utils/frag.8 deleted file mode 100644 index c2f67b58..00000000 --- a/disk-utils/frag.8 +++ /dev/null @@ -1,47 +0,0 @@ -.\" Copyright 1992,1993,1994 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.TH FRAG 8 "8 January 1994" "Linux 0.99" "Linux Programmer's Manual" -.SH NAME -frag \- simple fragmentation checker -.SH SYNOPSIS -.B /usr/sbin/frag -.B "[ \-s [ \-s ]]" -filename ... -.SH DESCRIPTION -.B frag -will report the file system fragmentation on a specified -.IR filename . -If the -.I filename -is a directory, -.B frag -will recursively descend the directory. -.SH OPTIONS -.TP -.B \-s -Silent (may be set to 1 or 2). The first -.B \-s -eliminates the file by file statistics, and just prints the -examined directories and a summary. The second -.B \-s -eliminates the printing of the directories, and just prints a -summary. This option is useful when -.B frag -is used on a directory. -.SH "SEE ALSO" -.BR mkfs (8), -.BR fsck (8), -.BR mkefs (8), -.BR efsck (8) -.SH BUGS -.B frag -will get caught in an infinite loop in the /proc filesystem. -.SH AUTHORS -V1.0 by Werner Almesberger -.br -V1.1 by Steffen Zahn, adding directory recursion -.br -V1.2 by Rob Hooft, adding hole counts -.br -V1.3 by Steffen Zahn, ignore symlinks, -don't cross filesys borders, get filesystem block size at runtime diff --git a/disk-utils/frag.c b/disk-utils/frag.c deleted file mode 100644 index 0098e02f..00000000 --- a/disk-utils/frag.c +++ /dev/null @@ -1,311 +0,0 @@ -/* frag.c - simple fragmentation checker - V1.0 by Werner Almesberger - V1.1 by Steffen Zahn, adding directory recursion - V1.2 by Rob Hooft, adding hole counts - V1.3 by Steffen Zahn, email: szahn%masterix@emndev.siemens.co.at - 14 Nov 93 - - ignore symlinks, - - don't cross filesys borders - - get filesystem block size at runtime - V1.4 by Michael Bischoff to handle - indirect blocks better, but only for ext2fs - (applied by faith@cs.unc.edu, Sat Feb 4 22:06:27 1995) - - TODO: - handle hard links - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for FIBMAP */ - -typedef struct StackElem { - struct StackElem *backref, *next; - char name[NAME_MAX]; - char dir_seen; - char from_cmd_line; -} StackElem; - -StackElem *top = NULL; - - -void discard( void ) -{ - StackElem *se = top; - if( se == NULL ) - return ; - top = se->next; - free(se); -} - -void push( StackElem * se ) -{ - se -> next = top; - top = se; -} - -char *p2s( StackElem *se, char *path ) -{ - char *s; - if( se->backref!=NULL ) { - path = p2s( se->backref, path ); - if( path[-1]!='/' ) - *path++ = '/'; - } - s = se->name; - while( *s ) - *path++ = *s++; - return path; -} - -char *path2str( StackElem *se, char *path ) -{ - *(p2s( se, path ))=0; - return path; -} - -void *xmalloc( size_t size ) -{ - void *p; - if( (p=malloc(size))==NULL ) { - fprintf(stderr,"\nvirtual memory exhausted.\n"); - exit(1); - } - return p; -} - -int main(int argc,char **argv) -{ - int fd,last_phys_block, - fragments_in_file, blocks_in_file, - blocks,current_phys_block, - this_fragment, largest_fragment, i; - long sum_blocks=0, sum_frag_blocks=0, sum_files=0, sum_frag_files=0; - long num_hole=0, sum_hole=0, hole; - struct stat st; - struct statfs stfs; - StackElem *se, *se1; - char path[PATH_MAX], pathlink[PATH_MAX], *p; - DIR *dir; - struct dirent *de; - char silent_flag=0; - dev_t local_fs; - int block_size; - - if (argc < 2) - { - fprintf(stderr,"usage: %s [-s [-s]] filename ...\n",argv[0]); - exit(1); - } - argc--; argv++; - while (argc>0) - { - p = *argv; - if( *p=='-' ) - while( *++p ) - switch( *p ) - { - case 's': - silent_flag++; /* may be 1 or 2 */ - break; - default: - fprintf(stderr,"\nunknown flag %c\n", *p ); - exit(1); - } - else - { - se = xmalloc( sizeof(StackElem) ); - se->backref=NULL; se->dir_seen=0; se->from_cmd_line=1; - strcpy( se->name, p ); - push(se); - } - argc--; argv++; - } - while ( top != NULL) - { - se = top; - if( se->dir_seen ) - discard(); - else - { - path2str( se, path ); - if( readlink( path, pathlink, sizeof(pathlink) )>=0 ) - { /* ignore symlinks */ - if(silent_flag<1) - { - printf("symlink %s\n", path ); - } - discard(); - } - else if( stat( path,&st) < 0) - { - perror( path ); - discard(); - } - else if( !se->from_cmd_line && (local_fs!=st.st_dev) ) - { /* do not cross filesystem borders */ - if(silent_flag<2) - { - printf("different filesystem %s\n", path ); - } - discard(); - } - else - { - if( se->from_cmd_line ) - { - local_fs = st.st_dev; - if ( statfs( path, &stfs )<0 ) - { - perror( path ); - block_size = 1024; - } - else - block_size = stfs.f_bsize; - } - if( S_ISREG(st.st_mode)) /* regular file */ - { - if ( (fd = open( path ,O_RDONLY)) < 0 ) - { - perror( path ); - discard(); - } - else - { - last_phys_block = -1; - fragments_in_file = 0; - hole = 0; this_fragment=0; - largest_fragment=0; - blocks_in_file = (st.st_size+block_size-1)/block_size; - for (blocks = 0; blocks < blocks_in_file; blocks++) - { - current_phys_block = blocks; - if (ioctl(fd,FIBMAP,¤t_phys_block) < 0) - { - perror(path); - break; - } - if (current_phys_block) { /* no hole here */ - int indirect; - /* indirect is the number of indirection */ - /* blocks which must be skipped */ - indirect = 0; - /* every 256 blocks there is an indirect block, - the first of these is before block 12 */ - if (blocks >= 12 && (blocks-12) % 256 == 0) - ++indirect; - /* there is a block pointing to the indirect - blocks every 64K blocks */ - if (blocks >= 256+12 && (blocks-256-12) % 65536 == 0) - ++indirect; /* 2nd indirect block */ - /* there is a single triple indirect block */ - if (blocks == 65536 + 256 + 12) - ++indirect; - if (last_phys_block == current_phys_block-1-indirect) - this_fragment++; - else { /* start of first or new fragment */ - if( largest_fragment1 ) - { - sum_frag_blocks+=blocks_in_file-largest_fragment; - sum_frag_files++; - } - discard(); - close(fd); - } - } - else if( S_ISDIR( st.st_mode ) ) /* push dir contents */ - { - if( (dir=opendir( path ))==NULL ) - { - perror(path); - discard(); - } - else - { - if( silent_flag<2 ) - printf("reading %s\n", path); - while( (de=readdir(dir))!=NULL ) - { - if( (strcmp(de->d_name,".")!=0) - && (strcmp(de->d_name,"..")!=0) ) - { - se1 = xmalloc( sizeof(StackElem) ); - se1->backref=se; se1->dir_seen=0; - se1->from_cmd_line=0; - strcpy( se1->name, de->d_name ); - push(se1); - } - } - closedir( dir ); - se->dir_seen=1; - } - } - else /* if( S_ISREG(st.st_mode)) */ - discard(); - } - } /* if( se->dir_seen ) */ - } /* while ( top != NULL) */ - if (sum_files>1) - { - printf("\nsummary:\n"); - printf(" %3ld%% file fragmentation (%ld of %ld files contain fragments)\n", - sum_files<1 ? 0L : sum_frag_files*100/sum_files, - sum_frag_files, sum_files); - printf(" %3ld%% block fragmentation (%ld of %ld blocks are in fragments)\n", - sum_blocks<1 ? 0L : sum_frag_blocks*100/sum_blocks, - sum_frag_blocks, sum_blocks); - if (num_hole>1) - printf(" %ld files contain %ld blocks in holes\n", - num_hole,sum_hole); - } - exit(0); -} diff --git a/disk-utils/fsck.minix.c b/disk-utils/fsck.minix.c index ae1d7b1a..ba64bf34 100644 --- a/disk-utils/fsck.minix.c +++ b/disk-utils/fsck.minix.c @@ -317,7 +317,7 @@ int check_zone_nr(unsigned short * nr, int * corrected) return 0; } - +#ifdef HAVE_MINIX2 int check_zone_nr2 (unsigned int *nr, int *corrected) { if (!*nr) @@ -336,6 +336,7 @@ int check_zone_nr2 (unsigned int *nr, int *corrected) } return 0; } +#endif /* * read-block reads block nr into the buffer at addr. @@ -627,11 +628,12 @@ struct minix_inode * get_inode(unsigned int nr) nr); print_current_name(); printf("'\n"); - if (repair) + if (repair) { if (ask("Mark in use",1)) mark_inode(nr); - else + } else { errors_uncorrected = 1; + } } if (S_ISDIR(inode->i_mode)) directory++; @@ -762,7 +764,7 @@ static int add_zone(unsigned short * znr, int * corrected) return block; } - +#ifdef HAVE_MINIX2 static int add_zone2 (unsigned int *znr, int *corrected) { int result; @@ -795,6 +797,7 @@ static int add_zone2 (unsigned int *znr, int *corrected) zone_count[block]--; return block; } +#endif static void add_zone_ind(unsigned short * znr, int * corrected) { @@ -812,7 +815,9 @@ static void add_zone_ind(unsigned short * znr, int * corrected) write_block(block, blk); } -static void add_zone_ind2 (unsigned int *znr, int *corrected) +#ifdef HAVE_MINIX2 +static void +add_zone_ind2 (unsigned int *znr, int *corrected) { static char blk[BLOCK_SIZE]; int i, chg_blk = 0; @@ -827,6 +832,7 @@ static void add_zone_ind2 (unsigned int *znr, int *corrected) if (chg_blk) write_block (block, blk); } +#endif static void add_zone_dind(unsigned short * znr, int * corrected) { @@ -844,6 +850,7 @@ static void add_zone_dind(unsigned short * znr, int * corrected) write_block(block, blk); } +#ifdef HAVE_MINIX2 static void add_zone_dind2 (unsigned int *znr, int *corrected) { @@ -877,6 +884,7 @@ add_zone_tind2 (unsigned int *znr, int *corrected) if (blk_chg) write_block (block, blk); } +#endif void check_zones(unsigned int i) { @@ -945,18 +953,20 @@ void check_file(struct minix_inode * dir, unsigned int offset) name_depth++; inode = get_inode(ino); name_depth--; - if (!offset) + if (!offset) { if (!inode || strcmp(".",name)) { print_current_name(); printf(": bad directory: '.' isn't first\n"); errors_uncorrected = 1; } else return; - if (offset == dirsize) + } + if (offset == dirsize) { if (!inode || strcmp("..",name)) { print_current_name(); printf(": bad directory: '..' isn't second\n"); errors_uncorrected = 1; } else return; + } if (!inode) return; if (name_depth < MAX_DEPTH) @@ -1230,12 +1240,12 @@ int main(int argc, char ** argv) #endif while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) usage(); else device_name = argv[0]; - else while (*++argv[0]) + } else while (*++argv[0]) switch (argv[0][0]) { case 'l': list=1; break; case 'a': automatic=1; repair=1; break; diff --git a/disk-utils/mkfs.8 b/disk-utils/mkfs.8 index 57132a48..2dd61648 100644 --- a/disk-utils/mkfs.8 +++ b/disk-utils/mkfs.8 @@ -55,13 +55,8 @@ This is really only useful for testing. .TP .BI -t \ fstype Specifies the type of file system to be built. -If not specified, the type is deduced by searching for -.I filesys -in -.I /etc/fstab -and using the corresponding entry. -If the type can not be deduced, the default file system type -(currently minix) is used. +If not specified, the default file system type +(currently ext2) is used. .TP .B fs-options File system-specific options to be passed to the real file diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c index db7aefae..c34da532 100644 --- a/disk-utils/mkfs.minix.c +++ b/disk-utils/mkfs.minix.c @@ -624,7 +624,7 @@ int main(int argc, char ** argv) #endif while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) { BLOCKS = strtol(argv[0],&tmp,0); if (*tmp) { @@ -634,7 +634,7 @@ int main(int argc, char ** argv) } } else device_name = argv[0]; - else { + } else { if(argv[0][1] == 'l') { listfile = argv[1]; argv++; diff --git a/disk-utils/mkswap.8 b/disk-utils/mkswap.8 index 1e14167b..2df606c5 100644 --- a/disk-utils/mkswap.8 +++ b/disk-utils/mkswap.8 @@ -1,83 +1,93 @@ -.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) +.\" Copyright 1998 Andries E. Brouwer (aeb@cwi.nl) +.\" .\" May be distributed under the GNU General Public License -.\" Modified with suggestions from Linus, Mon Feb 1 21:40:49 1993 -.\" Modified with patches from Kai, Wed Jun 22 21:54:56 1994 -.\" Patches from jaggy@purplet.demon.co.uk (Mike Jagdis), Wed Feb 8 1995 -.\" Added comments from Nick Holloway, Sat Feb 11 1995, faith@cs.unc.edu -.\" " -.TH MKSWAP 8 "February 1995" "Linux 1.0" "Linux Programmer's Manual" +.\" Rewritten for 2.1.117, aeb, 981010. +.\" +.TH MKSWAP 8 "1 December 1998" "Linux 2.1.117" "Linux Programmer's Manual" .SH NAME mkswap \- set up a Linux swap area .SH SYNOPSIS -.B "mkswap [ \-c ]" -.IB device " [" size-in-blocks "]" +.BI "mkswap [\-c] [\-v" N "] [\-f] " device " [" size "]" .SH DESCRIPTION .B mkswap sets up a Linux swap area on a device or in a file. +(After creating the swap area, you need the +.B swapon +command to start using it. Usually swap areas are listed in +.I /etc/fstab +so that they can be taken into use at boot time by a +.B swapon -a +command in some boot script.) + The .I device -is usually of the following form: - -.nf -.RS -/dev/hda[1-8] -/dev/hdb[1-8] -/dev/sda[1-8] -/dev/sdb[1-8] -.RE -.fi +argument will usually be a disk partition (something like +.I /dev/hda4 +or +.IR /dev/sdb7 ) +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. The -.I size-in-blocks -parameter is the desired size of the file system, in blocks. This -information is determined automatically by +.I size +parameter is superfluous but retained for backwards compatibility. +(It specifies the desired size of the swap area in 1024-byte blocks. .B mkswap -if it is omitted. Block counts are rounded down so that the total -size is an integer multiple of the machine's page size. Only block -counts in the range MINCOUNT..MAXCOUNT are allowed. If the block count -exceeds the MAXCOUNT, it is truncated to that value and a warning -message is issued. +will use the entire partition or file if it is omitted.) -The MINCOUNT and MAXCOUNT values for a swap area are: +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 +signature. -.RS -MINCOUNT = 10 * PAGE_SIZE / 1024 -.br -MAXCOUNT = (PAGE_SIZE - 10) * 8 * PAGE_SIZE / 1024 -.RE +In the old style, the rest of this first page was a bit map, +with a 1 bit for each usable page of the swap area. +Since the first page holds this bit map, the first bit is 0. +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. +On an alpha and sparc64, with S=8192, the useful area is at most +535560992 bytes (almost 512 MB with the same proviso). -For example, on a machine with 4kB pages (e.g., x86), we get: +The old setup wastes most of this bitmap page, because zero bits +denote bad blocks or blocks past the end of the swap space, +and a simple integer suffices to indicate the size of the swap space, +while the bad blocks, if any, can simply be listed. Nobody wants +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 is now (2^31 - 2*S) bytes, +roughly 2 GB. -.RS -MINCOUNT = 10 * 4096 / 1024 = 40 -.br -MAXCOUNT = (4096 - 10) * 8 * 4096 / 1024 = 130752 -.RE +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. -As each block is 1kB large, the swap area in this example could have a -size that is anywhere in the range from 40kB up to 127.6875MB. +Presently, Linux allows 8 swap areas. The areas in use can be seen +in the file +.I /proc/swaps +(since 2.1.25). -If you don't know the page size that your machine uses, you may be -able to look it up with "cat /proc/cpuinfo". +.B mkswap +refuses areas smaller than 10 pages. -The reason for the limit on MAXCOUNT is that a single page is used to -hold the swap bitmap at the start of the swap area, where each bit -represents a single page. The reason for the -10, is that the -signature is "SWAP-SPACE" -- 10 characters. +If you don't know the page size that your machine uses, you may be +able to look it up with "cat /proc/cpuinfo" (or you may not - +the contents of this file depend on architecture and kernel version). To setup a swap file, it is necessary to create that file before running -.B mkswap . -A sequence of commands similar to the following is reasonable for this -purpose: +.B mkswap , +e.g. using a command like .nf .RS -# dd if=/dev/zero of=swapfile bs=1024 count=8192 -# mkswap swapfile 8192 -# sync -# swapon swapfile +# dd if=/dev/zero of=swapfile bs=1024 count=65536 .RE .fi @@ -88,19 +98,34 @@ to create the file is not acceptable). .SH OPTIONS .TP .B \-c -Check the device for bad blocks before creating the file system. If any -are found, the count is printed. This option is meant to be used for swap -partitions -.BR only , -and should -.B not -be used for regular files! To make sure that regular files do not contain -bad blocks, the partition that contains the regular file should have been -created with -.BR "mkfs -c" . +Check the device (if it is a block device) for bad blocks +before creating the swap area. +If any are found, the count is printed. +.TP +.B \-f +On SPARC, force creation of the swap area. +Without this option +.B mkswap +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 +.B \-v0 +Create an old style swap area. +.TP +.B \-v1 +Create a new style swap area. + +.LP +If no \-v option is given, +.B mkswap +will default to old style if the size of the swap area does not +exceed the maximum size of an old style swap area, and also if +the current kernel is older than 2.1.117 (and also if PAGE_SIZE +is less than 2048). +The new style header does not touch the first block, so may be +preferable (also if the swap area is small), in case you have +a boot loader or disk label there. + .SH "SEE ALSO" -.BR fsck (8), -.BR mkfs (8), -.BR fdisk (8) -.SH AUTHOR -Linus Torvalds (torvalds@cs.helsinki.fi) +.BR fdisk (8), +.BR swapon (8) diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index 49447f2a..b3402366 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -8,15 +8,21 @@ /* * 20.12.91 - time began. Got VM working yesterday by doing this by hand. * - * Usuage: mkswap [-c] device [size-in-blocks] + * Usuage: 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. */ #include @@ -24,26 +30,85 @@ #include #include #include -#include +#include /* for _IO */ +#include #include -#include +#include /* for PAGE_SIZE and PAGE_SHIFT */ +#ifndef _IO +/* pre-1.3.45 */ #define BLKGETSIZE 0x1260 - -#ifndef __linux__ -# define volatile +#else +/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ +#define BLKGETSIZE _IO(0x12,96) #endif -#define TEST_BUFFER_PAGES 8 - static char * program_name = "mkswap"; static char * device_name = NULL; static int DEV = -1; static long PAGES = 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; -static int signature_page[PAGE_SIZE/sizeof(int)]; +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; + + strncpy(sp+pagesize-10, sig, 10); +} + +#define V0_MAX_PAGES (8 * (pagesize - 10)) +#define V1_MAX_PAGES ((0x7fffffff / pagesize) - 1) + +#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) static void bit_set (unsigned int *addr, unsigned int nr) { @@ -66,41 +131,56 @@ 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) +void fatal_error(const char * fmt_string) { fprintf(stderr,fmt_string,program_name,device_name); exit(1); } -#define usage() fatal_error("Usage: %s [-c] /dev/name [blocks]\n") +#define usage() fatal_error("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n") #define die(str) fatal_error("%s: " str "\n") -void check_blocks(void) -{ +void +page_ok(int page) { + if (version==0) + bit_set(signature_page, 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; - static char buffer[PAGE_SIZE]; + char *buffer; + buffer = malloc(pagesize); + if (!buffer) + die("Out of memory"); current_page = 0; while (current_page < PAGES) { if (!check) { - bit_set(signature_page,current_page++); + page_ok(current_page++); continue; } - 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_set(signature_page,current_page++); + page_ok(current_page++); } if (badpages) printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); @@ -117,12 +197,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) { @@ -133,26 +214,27 @@ 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 int +get_size(const char *file) { int fd; int 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; } @@ -161,28 +243,41 @@ int main(int argc, char ** argv) { char * tmp; struct stat statbuf; + int maxpages; int goodpages; + int offset; + int force = 0; - memset(signature_page,0,PAGE_SIZE); if (argc && *argv) program_name = *argv; + + init_signature_page(); /* get pagesize */ + while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) { - PAGES = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10); + int blocks_per_page = pagesize/1024; + PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; if (*tmp) usage(); } else device_name = argv[0]; - else while (*++argv[0]) - switch (argv[0][0]) { - case 'c': check=1; break; - default: usage(); + } 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(); } - } - if (device_name && !PAGES) { - PAGES = get_size(device_name) / PAGE_SIZE; + } } if (!device_name) { fprintf(stderr, @@ -190,17 +285,38 @@ int main(int argc, char ** argv) program_name); usage(); } + if (!PAGES) { + PAGES = get_size(device_name); + } + + 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(); + } if (PAGES < 10) { fprintf(stderr, "%s: error: swap area needs to be at least %ldkB\n", - program_name, (long)(10 * PAGE_SIZE / 1024)); + program_name, (long)(10 * pagesize / 1024)); usage(); } - if (PAGES > 8 * (PAGE_SIZE - 10)) { - PAGES = 8 * (PAGE_SIZE - 10); + maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); + 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); @@ -210,19 +326,56 @@ int main(int argc, char ** argv) check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) die("Will not try to make swapdevice on '%s'"); - check_blocks(); - 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(1); + } + } + } +#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", - (long)(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"); + /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) diff --git a/disk-utils/setfdprm.c b/disk-utils/setfdprm.c index fee55300..62234f3a 100644 --- a/disk-utils/setfdprm.c +++ b/disk-utils/setfdprm.c @@ -103,7 +103,7 @@ gap rate spec1 fmt_gap\n",name); exit(1); } -void +int main(int argc,char **argv) { int fd; @@ -153,4 +153,5 @@ main(int argc,char **argv) else find_params(cmd,fd,argv[2]); /* not reached */ + return 0; } diff --git a/example.files/filesystems b/example.files/filesystems new file mode 100644 index 00000000..74e1b517 --- /dev/null +++ b/example.files/filesystems @@ -0,0 +1,19 @@ + ext2 + vfat + umsdos + msdos + iso9660 + minix + ntfs + hpfs + ufs + sysv + romfs + reiserfs +nodev autofs +nodev proc +nodev smbfs +nodev nfs +nodev coda +nodev devpts +nodev devfs diff --git a/example.files/issue0 b/example.files/issue0 new file mode 100644 index 00000000..285f71af --- /dev/null +++ b/example.files/issue0 @@ -0,0 +1 @@ +This is \n (\s \m \r) \d diff --git a/example.files/syslog.conf b/example.files/syslog.conf deleted file mode 100644 index 66e436b4..00000000 --- a/example.files/syslog.conf +++ /dev/null @@ -1,12 +0,0 @@ -kern.* /var/adm/kernlog -mark.info;daemon.notice;mail.crit /var/adm/syslog -mail.info;mail.debug /var/adm/maillog -daemon.info /var/adm/daemon -lpr.info /var/adm/lpd-errs -auth.notice /var/adm/authlog -*.err /var/adm/syslog -*.notice;auth.debug /var/adm/sysdebug -*.alert /dev/console -news.alert;news.crit;news.err /var/adm/news -news.warning;news.notice /var/adm/news -news.info;news.debug /var/adm/news diff --git a/example.files/syslog.conf.alt b/example.files/syslog.conf.alt deleted file mode 100644 index c5923c4c..00000000 --- a/example.files/syslog.conf.alt +++ /dev/null @@ -1,22 +0,0 @@ -# Log all kernel messages to the console. -# Logging much else clutters up the screen. -kern.* /dev/console -#kern.* /dev/cua1 - -# Log anything (except mail) of level info or higher. -# Don't log private authentication messages! -*.info;mail.none;authpriv.none /var/adm/messages - -# The authpriv file has restricted access. -authpriv.* /var/adm/secure - -# Log all the mail messages in one place. -mail.* /var/adm/maillog - -# Everybody gets emergency messages, plus log them on another -# machine. -*.emerg * - -# Save mail and news errors of level err and higher in a -# special file. -uucp,news.crit /var/adm/spooler diff --git a/fdisk/Makefile b/fdisk/Makefile new file mode 100644 index 00000000..e5415acd --- /dev/null +++ b/fdisk/Makefile @@ -0,0 +1,68 @@ +# 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 ../MCONFIG + +MAN8= +SBIN= + +ifneq "$(CPU)" "sparc" +# fsck and mkfs will compile, but there is no kernel support on sparc +ifneq "$(CPU)" "m68k" +MAN8:=$(MAN8) fdisk.8 cfdisk.8 sfdisk.8 +SBIN:=$(SBIN) fdisk cfdisk sfdisk +endif +else +MAN8:=$(MAN8) fdisk.8 +SBIN:=$(SBIN) fdisk +endif + +all: $(SBIN) + +cfdisk.o: cfdisk.c +ifeq "$(HAVE_SLANG)" "yes" + $(CC) -c $(CFLAGS) -DSLCURSES=1 $< -o $@ +else +ifeq "$(HAVE_NCURSES)" "yes" + $(CC) -c $(CFLAGS) $< -o $@ +else + : +endif +endif + +cfdisk: cfdisk.o llseek.o +ifeq "$(HAVE_SLANG)" "yes" + $(CC) $(LDFLAGS) $^ -o $@ $(LIBSLANG) +else +ifeq "$(HAVE_NCURSES)" "yes" + $(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES) -lm +else + @echo $@ not made since it requires ncurses or slang +endif +endif + +# not installed by default +activate: sfdisk + rm -f activate + ln -s sfdisk activate + +fdisk: fdisk.o llseek.o fdiskbsdlabel.o fdisksgilabel.o fdisksunlabel.o \ + fdiskaixlabel.o +fdisk.o: fdisk.c fdisk.h +fdiskbsdlabel.o: fdiskbsdlabel.c fdisk.h fdiskbsdlabel.h +fdisksunlabel.o: fdisksunlabel.c fdisksunlabel.h fdisk.h +fdiskaixlabel.o: fdiskaixlabel.c fdiskaixlabel.h fdisk.h +sfdisk: sfdisk.o + +install: all + $(INSTALLDIR) $(SBINDIR) + $(INSTALLBIN) $(SBIN) $(SBINDIR) + $(INSTALLDIR) $(MAN8DIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +.PHONY: clean +clean: + -rm -f *.o *~ core $(SBIN) diff --git a/disk-utils/README.cfdisk b/fdisk/README.cfdisk similarity index 100% rename from disk-utils/README.cfdisk rename to fdisk/README.cfdisk diff --git a/disk-utils/README.fdisk b/fdisk/README.fdisk similarity index 99% rename from disk-utils/README.fdisk rename to fdisk/README.fdisk index 40f54b4b..86b18252 100644 --- a/disk-utils/README.fdisk +++ b/fdisk/README.fdisk @@ -577,3 +577,7 @@ Verify command before writing any changes to disk. If you set the disk geometry (tracks per cylinder, or sectors per track) to an incorrect value, you may lose all data on your disk. + +Do create BSD/SUN and/or IRIX/SGI disk labels only when you are sure +that you want them. Both features are intended to allow you READing +those labels and prevent unintentional formatting of these disks. diff --git a/disk-utils/cfdisk.8 b/fdisk/cfdisk.8 similarity index 98% rename from disk-utils/cfdisk.8 rename to fdisk/cfdisk.8 index c7ac9417..c8391af2 100644 --- a/disk-utils/cfdisk.8 +++ b/fdisk/cfdisk.8 @@ -395,9 +395,12 @@ Prints the partition table in specified formats. can be one or more of "r", "s" or "t". See the .BR p rint command (above) for more information on the print formats. +.SH "EXIT STATUS" +0: No errors; 1: Invocation error; 2: I/O error; +3: cannot get geometry; 4: bad partition table on disk. .SH "SEE ALSO" fdisk(8) .SH BUGS -The current version does not support multiple disks (future addition). +The current version does not support multiple disks. .SH AUTHOR Kevin E. Martin (martin@cs.unc.edu) diff --git a/disk-utils/cfdisk.c b/fdisk/cfdisk.c similarity index 92% rename from disk-utils/cfdisk.c rename to fdisk/cfdisk.c index f0b5482f..96ddbbf2 100644 --- a/disk-utils/cfdisk.c +++ b/fdisk/cfdisk.c @@ -29,9 +29,15 @@ * >2GB patches: Sat Feb 11 09:08:10 1995, faith@cs.unc.edu * Prettier menus: Sat Feb 11 09:08:25 1995, Janne Kukonlehto * - * Versions 0.8e-l: aeb@cwi.nl + * Versions 0.8e-n: aeb@cwi.nl * Recognition of NTFS / HPFS difference inspired by patches * from Marty Leisner + * Exit codes by Enrique Zanardi : + * 0: all went well + * 1: command line error + * 2: hardware problems [BAD_SEEK, BAD_READ, BAD_WRITE or BAD_OPEN]. + * 3: ioctl(fd, HDIO_GETGEO,...) failed [BAD_GEOMETRY]. + * 4: bad partition table on disk. [BAD_PRIMARY or BAD_LOGICAL]. * ****************************************************************************/ @@ -59,7 +65,6 @@ #include #include #include -#include #include #include /* for BLKRRPART */ @@ -72,7 +77,7 @@ typedef long ext2_loff_t; extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, unsigned int origin); -#define VERSION "0.8l" +#define VERSION "0.8n" #define DEFAULT_DEVICE "/dev/hda" #define ALTERNATE_DEVICE "/dev/sda" @@ -87,7 +92,8 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, #define MAX_SECTORS 63 #define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 +#define PART_TABLE_FLAG0 0x55 +#define PART_TABLE_FLAG1 0xAA #define UNUSABLE -1 #define FREE_SPACE 0x00 @@ -129,6 +135,7 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, #define YES_WRITE "Wrote partition table to disk" #define NO_WRITE "Did not write partition table to disk" #define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." +#define NOT_DOS_MBR_BOOTABLE "Not precisely one primary partition is bootable. DOS MBR cannot boot this." #define PRI_OR_LOG -1 #define PRIMARY -2 @@ -179,6 +186,55 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, || (x) == 7 || (x) == 0xb || (x) == 0xc || (x) == 0xe \ || (x) == 0x11 || (x) == 0x14 || (x) == 0x16 || (x) == 0x17) +struct partition { + unsigned char boot_ind; /* 0x80 - active */ + unsigned char head; /* starting head */ + unsigned char sector; /* starting sector */ + unsigned char cyl; /* starting cylinder */ + unsigned char sys_ind; /* What partition type */ + unsigned char end_head; /* end head */ + unsigned char end_sector; /* end sector */ + unsigned char end_cyl; /* end cylinder */ + unsigned char start4[4]; /* starting sector counting from 0 */ + unsigned char size4[4]; /* nr of sectors in partition */ +}; + +/* start_sect and nr_sects are stored little endian on all machines */ +/* moreover, they are not aligned correctly */ +void +store4_little_endian(unsigned char *cp, unsigned int val) { + cp[0] = (val & 0xff); + cp[1] = ((val >> 8) & 0xff); + cp[2] = ((val >> 16) & 0xff); + cp[3] = ((val >> 24) & 0xff); +} + +unsigned int +read4_little_endian(unsigned char *cp) { + return (uint)(cp[0]) + ((uint)(cp[1]) << 8) + + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24); +} + +void +set_start_sect(struct partition *p, unsigned int start_sect) { + store4_little_endian(p->start4, start_sect); +} + +unsigned int +get_start_sect(struct partition *p) { + return read4_little_endian(p->start4); +} + +void +set_nr_sects(struct partition *p, unsigned int nr_sects) { + store4_little_endian(p->size4, nr_sects); +} + +unsigned int +get_nr_sects(struct partition *p) { + return read4_little_endian(p->size4); +} + #define ALIGNMENT 2 typedef union { struct { @@ -189,7 +245,7 @@ typedef union { unsigned char align[ALIGNMENT]; unsigned char buffer[0x1BE]; struct partition part[4]; - unsigned short flag; + unsigned char magicflag[2]; } p; } partition_table; @@ -280,6 +336,7 @@ char *partition_type[NUM_PART_TYPES] = { [0x16] = "Hidden DOS FAT16 (big)", [0x17] = "Hidden OS/2 HPFS or NTFS", [0x40] = "Venix 80286", + [0x41] = "PPC PReP boot", [0x51] = "Novell?", [0x52] = "Microport", [0x63] = "GNU HURD", @@ -298,6 +355,7 @@ char *partition_type[NUM_PART_TYPES] = { [0xDB] = "CP/M", [0xE1] = "DOS access", [0xE3] = "DOS R/O", + [0xEB] = "BeOS fs", [0xF2] = "DOS secondary", [0xFF] = "BBT" }; @@ -438,7 +496,7 @@ void print_warning(char *s) void die_x(int ret); -void fatal(char *s) +void fatal(char *s, int ret) { char str[LINE_LENGTH]; @@ -450,10 +508,10 @@ void fatal(char *s) putchar(BELL); /* CTRL-G */ refresh(); (void)getch(); - die_x(1); + die_x(ret); } else { fprintf(stderr, "FATAL ERROR: %s\n", s); - exit(1); + exit(ret); } } @@ -481,17 +539,17 @@ void die_x(int ret) void read_sector(char *buffer, int sect_num) { if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); + fatal(BAD_SEEK, 2); if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); + fatal(BAD_READ, 2); } void write_sector(char *buffer, int sect_num) { if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); + fatal(BAD_SEEK, 2); if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); + fatal(BAD_WRITE, 2); } void dos_copy_to_info(char *to, int tosz, char *from, int fromsz) { @@ -565,7 +623,7 @@ void check_part_info(void) pri++; else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) log++; - if (is_extended(ext_info.id)) + if (is_extended(ext_info.id)) { if (log > 0) pri++; else { @@ -576,11 +634,12 @@ void check_part_info(void) ext_info.id = FREE_SPACE; ext_info.num = PRIMARY; } + } if (pri >= 4) { for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (is_extended(ext_info.id)) + if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) { + if (is_extended(ext_info.id)) { if (p_info[i].first_sector >= ext_info.first_sector && p_info[i].last_sector <= ext_info.last_sector) { p_info[i].id = FREE_SPACE; @@ -601,16 +660,16 @@ void check_part_info(void) p_info[i].num = LOGICAL; } else p_info[i].id = UNUSABLE; - else /* if (!is_extended(ext_info.id)) */ + } else /* if (!is_extended(ext_info.id)) */ p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ + } else /* if (p_info[i].id > 0) */ while (0); /* Leave these alone */ } else { /* if (pri < 4) */ for (i = 0; i < num_parts; i++) { if (p_info[i].id == UNUSABLE) p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (is_extended(ext_info.id)) + if (p_info[i].id == FREE_SPACE) { + if (is_extended(ext_info.id)) { if (p_info[i].first_sector >= ext_info.first_sector && p_info[i].last_sector <= ext_info.last_sector) p_info[i].num = LOGICAL; @@ -628,9 +687,9 @@ void check_part_info(void) p_info[i].num = PRI_OR_LOG; else p_info[i].num = PRIMARY; - else /* if (!is_extended(ext_info.id)) */ + } else /* if (!is_extended(ext_info.id)) */ p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ + } else /* if (p_info[i].id > 0) */ while (0); /* Leave these alone */ } } @@ -742,11 +801,12 @@ int add_part(int num, int id, int flags, int first, int last, int offset, if (is_extended(ext_info.id) && log > 0) pri++; - if (IS_PRIMARY(num)) + if (IS_PRIMARY(num)) { if (pri >= 4) { return -1; /* no room for more */ } else pri++; + } for (i = 0; i < num_parts && p_info[i].last_sector < first; i++); @@ -902,15 +962,18 @@ void inc_logical(int i) struct MenuItem { - char key; /* Keyboard shortcut; if zero, then there is no more items in the menu item table */ + int key; /* Keyboard shortcut; if zero, then there is no more items in the menu item table */ char *name; /* Item name, should be eight characters with current implementation */ char *desc; /* Item description to be printed when item is selected */ }; -/* Actual function which prints the button bar and highlights the active button * - * Should not be called directly. Call function menuSelect instead. */ +/* + * Actual function which prints the button bar and highlights the active button + * Should not be called directly. Call function menuSelect instead. + */ -int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, char *available, int menuType, int current ) +int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, + char *available, int menuType, int current ) { int i, lmargin = x, ymargin = y; /* Print available buttons */ @@ -925,7 +988,8 @@ int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, char * i++; } if( !menuItems[i].key ) break; /* No more menu items */ - /* If selected item is not available and we have bypassed it, make current item selected */ + /* If selected item is not available and we have bypassed it, + make current item selected */ if( current < i && menuItems[current].key < 0 ) current = i; /* If current item is selected, highlight it */ if( current == i ) /*attron( A_REVERSE )*/ standout (); @@ -965,7 +1029,9 @@ int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, char * } } /* Print the description of selected item */ - mvaddstr( WARNING_START + 1, (COLUMNS - strlen( menuItems[current].desc )) / 2, menuItems[current].desc ); + mvaddstr( WARNING_START + 1, + (COLUMNS - strlen( menuItems[current].desc )) / 2, + menuItems[current].desc ); return y; } @@ -1085,7 +1151,8 @@ int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char * /* Should all keys to be accepted? */ if( key && (menuType & MENU_ACCEPT_OTHERS) ) break; /* Is pressed key among acceptable ones */ - if( key && (strchr(available, tolower(key)) || strchr(available, key)) ) break; + if( key && (strchr(available, tolower(key)) || strchr(available, key))) + break; /* The key has not been accepted so far -> let's reject it */ if( key ) { @@ -1268,14 +1335,15 @@ void clear_p_info(void) void fill_p_info(void) { - int p, i; + int pn, i, bs, bsz; + struct partition *p; struct hd_geometry geometry; partition_table buffer; partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; if ((fd = open(disk_device, O_RDWR)) < 0) { if ((fd = open(disk_device, O_RDONLY)) < 0) - fatal(BAD_OPEN); + fatal(BAD_OPEN, 2); opentype = O_RDONLY; print_warning(READONLY_WARN); if (curses_started) { @@ -1307,7 +1375,7 @@ void fill_p_info(void) } if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); /* probably a file or cdrom */ + fatal(BAD_GEOMETRY, 3); /* probably a file or cdrom */ read_sector(buffer.c.b, 0); @@ -1315,18 +1383,17 @@ void fill_p_info(void) if (!zero_table) { for (i = 0; i < 4; i++) { - int bs = buffer.p.part[i].start_sect; + p = & buffer.p.part[i]; + bs = get_start_sect(p); + bsz = get_nr_sects(p); - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, + if (p->sys_ind > 0 && + add_part(i, p->sys_ind, p->boot_ind, ((bs <= sectors) ? 0 : bs), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, + bs + bsz - 1, ((bs <= sectors) ? bs : 0), 1)) { - fatal(BAD_PRIMARY); + fatal(BAD_PRIMARY, 4); } if (is_extended(buffer.p.part[i].sys_ind)) tmp_ext = ext_info; @@ -1339,32 +1406,34 @@ void fill_p_info(void) read_sector(buffer.c.b, logical_sectors[logical++]); i = 4; do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - is_extended(buffer.p.part[p].sys_ind)); - p++); - - if (p < 4 && add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, + for (pn = 0; + pn < 4 && (!buffer.p.part[pn].sys_ind || + is_extended(buffer.p.part[pn].sys_ind)); + pn++); + + if (pn < 4) { + p = & buffer.p.part[pn]; + bs = get_start_sect(p); + bsz = get_nr_sects(p); + + if (add_part(i++, p->sys_ind, p->boot_ind, logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect, - 1)) { - fatal(BAD_LOGICAL); + logical_sectors[logical-1] + bs + bsz - 1, + bs, 1)) + fatal(BAD_LOGICAL, 4); } - for (p = 0; - p < 4 && !is_extended(buffer.p.part[p].sys_ind); - p++); - if (p < 4) { - logical_sectors[logical] = ext_info.first_sector - + ext_info.offset + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); + for (pn = 0; + pn < 4 && !is_extended(buffer.p.part[pn].sys_ind); + pn++); + if (pn < 4) { + p = & buffer.p.part[pn]; + bs = get_start_sect(p); + logical_sectors[logical] = ext_info.first_sector + + ext_info.offset + bs; + read_sector(buffer.c.b, logical_sectors[logical++]); } - } while (p < 4 && logical < MAXIMUM_PARTS-4); + } while (pn < 4 && logical < MAXIMUM_PARTS-4); } } } @@ -1376,10 +1445,10 @@ void fill_part_table(struct partition *p, partition_info *pi) p->boot_ind = pi->flags; p->sys_ind = pi->id; if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; + set_start_sect(p,pi->offset); else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; + set_start_sect(p,pi->first_sector + pi->offset); + set_nr_sects(p, pi->last_sector - (pi->first_sector+pi->offset) + 1); sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? heads*sectors*1024 - 1 : pi->first_sector+pi->offset); set_hsc(p->head, p->sector, p->cyl, sects); @@ -1403,7 +1472,8 @@ void fill_primary_table(partition_table *buffer) if (is_extended(ext_info.id)) fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - buffer->p.flag = PART_TABLE_FLAG; + buffer->p.magicflag[0] = PART_TABLE_FLAG0; + buffer->p.magicflag[1] = PART_TABLE_FLAG1; } void fill_logical_table(partition_table *buffer, partition_info *pi) @@ -1412,7 +1482,8 @@ void fill_logical_table(partition_table *buffer, partition_info *pi) int i, sects; for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) + if (i == logical || buffer->p.magicflag[0] != PART_TABLE_FLAG0 + || buffer->p.magicflag[1] != PART_TABLE_FLAG1) for (i = 0; i < SECTOR_SIZE; i++) buffer->c.b[i] = 0; @@ -1432,8 +1503,8 @@ void fill_logical_table(partition_table *buffer, partition_info *pi) p->boot_ind = 0; p->sys_ind = DOS_EXTENDED; - p->start_sect = pi->first_sector - ext_info.first_sector - ext_info.offset; - p->nr_sects = pi->last_sector - pi->first_sector + 1; + set_start_sect(p, pi->first_sector - ext_info.first_sector - ext_info.offset); + set_nr_sects(p, pi->last_sector - pi->first_sector + 1); sects = ((pi->first_sector/(sectors*heads) > 1023) ? heads*sectors*1024 - 1 : pi->first_sector); set_hsc(p->head, p->sector, p->cyl, sects); @@ -1442,12 +1513,13 @@ void fill_logical_table(partition_table *buffer, partition_info *pi) set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); } - buffer->p.flag = PART_TABLE_FLAG; + buffer->p.magicflag[0] = PART_TABLE_FLAG0; + buffer->p.magicflag[1] = PART_TABLE_FLAG1; } void write_part_table(void) { - int i, done = FALSE, len; + int i, ct, done = FALSE, len; partition_table buffer; struct stat s; int is_bdev; @@ -1521,6 +1593,14 @@ void write_part_table(void) print_warning(RRPART_FAILED); } else print_warning(YES_WRITE); + + /* Check: unique bootable primary partition? */ + ct = 0; + for (i = 0; i < num_parts; i++) + if (IS_PRIMARY(i) && p_info[i].flags == ACTIVE_FLAG) + ct++; + if (ct != 1) + print_warning(NOT_DOS_MBR_BOOTABLE); } void fp_printf(FILE *fp, char *format, ...) @@ -2049,7 +2129,7 @@ void change_id(int i) char id[LINE_LENGTH], def[LINE_LENGTH]; int num_types = 0; int num_across, num_down; - int len, new_id = LINUX; + int len, new_id = ((p_info[i].id == LINUX) ? LINUX_SWAP : LINUX); int y_start, y_end; int j, pos; @@ -2085,12 +2165,13 @@ void change_id(int i) if (!isxdigit(id[0])) return; new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) + if (len == 2) { if (isxdigit(id[1])) new_id = new_id*16 + (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); else return; + } } if (new_id == 0) @@ -2472,9 +2553,10 @@ Options: copyright(); } -int main(int argc, char **argv) +int +main(int argc, char **argv) { - char c; + int c; int i, len; setlocale(LC_CTYPE, ""); diff --git a/disk-utils/fdisk.8 b/fdisk/fdisk.8 similarity index 89% rename from disk-utils/fdisk.8 rename to fdisk/fdisk.8 index 576bce2e..6307b98e 100644 --- a/disk-utils/fdisk.8 +++ b/fdisk/fdisk.8 @@ -5,9 +5,9 @@ .SH NAME fdisk \- Partition table manipulator for Linux .SH SYNOPSIS -.BI "fdisk [\-b] [\-u] [" device ] +.BI "fdisk [\-u] [" device ] .sp -.BI "fdisk \-l [\-b] [\-u] [" "device ..." ] +.BI "fdisk \-l [\-u] [" "device ..." ] .sp .BI "fdisk \-s " "partition ..." .sp @@ -74,6 +74,17 @@ Do not start a partition that actually uses its first sector (like a swap partition) at cylinder 0, since that will destroy the disklabel. +An IRIX/SGI type disklabel can describe 16 partitions, +the eleventh of which should be an entire `volume' partition, +while the ninth should be labeled `volume header'. +The volume header will also cover the partition table, i.e., +it starts at block zero and extends by default over five cylinders. +The remaining space in the volume header may be used by header +directory entries. No partitions may overlap with the volume header. +Also do not change its type and make some file system on it, since +you will lose the partition table. Use this type of label only when +working with Linux on IRIX/SGI machines or IRIX/SGI disks under Linux. + A DOS type partition table can describe an unlimited number of partitions. In sector 0 there is room for the description of 4 partitions (called `primary'). One of these may be an @@ -170,13 +181,6 @@ List the partition tables for .BR /dev/ed[a-d] , and then exit. .TP -.B \-b -When listing partition tables, also output a `Begin' column, -as earlier versions of fdisk did by default. -(Note: the values in this column, when given in cylinder units, -cannot be larger than 1023. There is nothing wrong if Begin and Start -differ, at least not as far as Linux is concerned.) -.TP .B \-u When listing partition tables, give sizes in sectors instead of cylinders. @@ -206,8 +210,14 @@ Try them in the order .BR cfdisk , .BR fdisk , .BR sfdisk . +.PP +The IRIX/SGI type disklabel is currently not supported by the kernel. +Moreover, IRIX/SGI header directories are not fully supported yet. +.PP +The option `dump partition table to file' is missing. .\" .SH AUTHORS .\" A. V. Le Blanc (LeBlanc@mcc.ac.uk) .\" Bernhard Fastenrath (fasten@informatik.uni-bonn.de) .\" Jakub Jelinek (jj@sunsite.mff.cuni.cz) +.\" Andreas Neuper (ANeuper@GUUG.de) .\" and many others. diff --git a/disk-utils/fdisk.c b/fdisk/fdisk.c similarity index 78% rename from disk-utils/fdisk.c rename to fdisk/fdisk.c index d99a8b45..8cdc6df8 100644 --- a/disk-utils/fdisk.c +++ b/fdisk/fdisk.c @@ -49,6 +49,8 @@ * Tue Sep 26 17:07:54 1995: More patches from aeb. Fix segfaults, all >4GB. * Don't destroy random data if extd partition starts past 4GB, aeb, 950818. * Don't segfault on bad partition created by previous fdisk. + * Fixed for using variable blocksizes (needed by magnet-optical drive-patch) + * (from orschaer@cip.informatik.uni-erlangen.de) * Modified, Fri Jul 14 11:13:35 MET DST 1996, jj@sunsite.mff.cuni.cz: * editor for Sun disklabels. * Modified, Wed Jul 3 10:14:17 MET DST 1996, jj@sunsite.mff.cuni.cz: @@ -61,6 +63,9 @@ * [cfdisk on the other hand is nice and correct] * Try to avoid reading a CD-ROM. * Do not print Begin column -- it confuses too many people -- aeb, 980610. + * Modified, Sat Oct 3 14:40:17 MET DST 1998, ANeuper@GUUG.de + * Support SGI's partitioning -- an, 980930. + * Do the verify using LBA, not CHS, limits -- aeb, 981206. */ @@ -81,9 +86,12 @@ #include /* for BLKRRPART, BLKGETSIZE */ #include "fdisk.h" -#if defined(sparc) + #include "fdisksunlabel.h" -#endif +#include "fdisksgilabel.h" +#include "fdiskaixlabel.h" + +#include "../version.h" #define hex_val(c) ({ \ char _c = (c); \ @@ -92,8 +100,6 @@ }) -#define VERSION "2.8" /* util-linux version */ - #define DEFAULT_DEVICE "/dev/hda" #define ALTERNATE_DEVICE "/dev/sda" #define LINE_LENGTH 80 @@ -102,7 +108,7 @@ #define sector(s) ((s) & 0x3f) #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) -#define calculate(h,s,c) (sector(s) - 1 + sectors * \ +#define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \ ((h) + heads * cylinder(s,c))) #define set_hsc(h,s,c,sector) { \ s = sector % sectors + 1; \ @@ -166,18 +172,6 @@ get_nr_sects(struct partition *p) { return read4_little_endian(p->size4); } -#define ACTIVE_FLAG 0x80 - -#define EXTENDED 0x05 -#define WIN98_EXTENDED 0x0f -#define LINUX_PARTITION 0x81 -#define LINUX_SWAP 0x82 -#define LINUX_NATIVE 0x83 -#define LINUX_EXTENDED 0x85 - -#define IS_EXTENDED(i) \ - ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) - /* normally O_RDWR, -l option gives O_RDONLY */ static int type_open = O_RDWR; @@ -185,7 +179,7 @@ char *disk_device = DEFAULT_DEVICE, /* hda, unless specified */ *line_ptr, /* interactive input */ line_buffer[LINE_LENGTH], changed[MAXIMUM_PARTS], /* marks changed buffers */ - buffer[SECTOR_SIZE], /* first four partitions */ + buffer[MAX_SECTOR_SIZE], /* first four partitions */ *buffers[MAXIMUM_PARTS] /* pointers to buffers */ = {buffer, buffer, buffer, buffer}; @@ -193,21 +187,22 @@ int fd, /* the disk */ ext_index, /* the prime extended partition */ listing = 0, /* no aborts for fdisk -l */ nowarn = 0, /* no warnings for fdisk -l/-s */ - show_begin = 0, dos_compatible_flag = ~0, partitions = 4; /* maximum partition + 1 */ uint heads, sectors, cylinders, + sector_size = DEFAULT_SECTOR_SIZE, sector_offset = 1, display_factor = 1, /* in units/sector */ unit_flag = 1, - full_bits = 0, /* 1024 cylinders in sectors */ extended_offset = 0, /* offset of link pointers */ offsets[MAXIMUM_PARTS] = {0, 0, 0, 0}; int sun_label = 0; /* looking at sun disklabel */ +int sgi_label = 0; /* looking at sgi disklabel */ +int aix_label = 0; /* looking at aix disklabel */ struct partition *part_table[MAXIMUM_PARTS] /* partitions */ = {offset(buffer, 0), offset(buffer, 1), @@ -231,7 +226,12 @@ struct systypes sys_types[] = { {0x0c, "Win95 FAT32 (LBA)"}, {0x0e, "Win95 FAT16 (LBA)"}, {0x0f, "Win95 Extended (LBA)"}, + {0x11, "Hidden DOS FAT12"}, + {0x14, "Hidden DOS FAT16"}, + {0x16, "Hidden DOS FAT16 (big)"}, + {0x17, "Hidden OS/2 HPFS or NTFS"}, {0x40, "Venix 80286"}, + {0x41, "PPC PReP Boot"}, {0x51, "Novell?"}, {0x52, "Microport"}, /* or CPM? */ {0x63, "GNU HURD"}, /* or System V/386? */ @@ -256,6 +256,7 @@ struct systypes sys_types[] = { {0xdb, "CP/M"}, /* or Concurrent DOS? */ {0xe1, "DOS access"}, {0xe3, "DOS R/O"}, + {0xeb, "BeOS fs"}, {0xf2, "DOS secondary"}, {0xff, "BBT"}, /* (bad track table) */ { 0, NULL } @@ -275,10 +276,21 @@ void fatal(enum failure why) switch (why) { case usage: message = -"Usage: fdisk [-b] [-u] [/dev/hdx] Change partition table\n" -" fdisk -l [-b] [-u] [/dev/hdx] List partition table(s)\n" -" fdisk -s /dev/hdxn Give partition size(s)\n" -" fdisk -v Give fdisk version\n"; +"Usage: fdisk [-b SSZ] [-u] [DISK] Change partition table\n" +" fdisk -l [-b SSZ] [-u] [DISK] List partition table(s)\n" +" fdisk -s PARTITION Give partition size(s) in blocks\n" +" fdisk -v Give fdisk version\n" +"Here DISK is something like /dev/hdb or /dev/sda\n" +"and PARTITION is something like /dev/hda7\n" +"-u: give Start and End in sector (instead of cylinder) units\n" +"-b 2048: (for certain MO drives) use 2048-byte sectors\n"; + break; + case no_device: + message = "A disk block device is needed.\n"; + break; + case no_partition: + message = "Given name does not refer to a partition,\n" + "or maybe not even to a block device.\n"; break; case unable_to_open: sprintf(error, "Unable to open %s\n", disk_device); @@ -324,6 +336,29 @@ void menu(void) " w write table to disk and exit\n" " x extra functionality (experts only)" ); + else if(sgi_label) + puts("Command action\n" + " a select bootable partition\n" /* sgi flavour */ + " b edit bootfile entry\n" /* sgi */ + " c select sgi swap partition\n" /* sgi flavour */ + " d delete a partition\n" + " l list known partition types\n" + " m print this menu\n" + " n add a new partition\n" + " o create a new empty DOS partition table\n" + " p print the partition table\n" + " q quit without saving changes\n" + " t change a partition's system id\n" + " u change display/entry units\n" + " v verify the partition table\n" + " w write table to disk and exit\n" + ); + else if(aix_label) + puts("Command action\n" + " m print this menu\n" + " o create a new empty DOS partition table\n" + " q quit without saving changes\n" + ); else puts("Command action\n" " a toggle a bootable flag\n" @@ -369,7 +404,8 @@ void xmenu(void) " b move beginning of data in a partition\n" /* !sun */ " c change number of cylinders\n" " d print the raw data in the partition table\n" - " e list extended partitions\n" /* sun */ + " e list extended partitions\n" /* !sun */ + " g create an IRIX partition table\n" /* sgi */ " h change number of heads\n" " m print this menu\n" " p print the partition table\n" @@ -381,17 +417,24 @@ void xmenu(void) ); } +int +get_sysid(int i) { + return ( + sun_label ? sunlabel->infos[i].id : + sgi_label ? sgi_get_sysid(i) : part_table[i]->sys_ind); +} + +struct systypes * +get_sys_types(void) { + return ( + sun_label ? sun_sys_types : + sgi_label ? sgi_sys_types : sys_types); +} + char *partition_type(unsigned char type) { int i; - struct systypes *types; - -#if defined(sparc) - if (sun_label) - types = sun_sys_types; - else -#endif - types = sys_types; + struct systypes *types = get_sys_types(); for (i=0; types[i].name; i++) if (types[i].index == type) @@ -485,34 +528,26 @@ int warn_geometry(void) return 1; } -uint rounded(uint calcul, uint start) -{ - uint i; - if (!full_bits) - return calcul; - while ((i = calcul + full_bits) <= start) - calcul = i; - return calcul; -} - void update_units(void) { - full_bits = 1024 * heads * sectors; - if (unit_flag && full_bits) - display_factor = full_bits >> 10; - else display_factor = 1; + int cyl_units = heads * sectors; + + if (unit_flag && cyl_units) + display_factor = cyl_units; + else + display_factor = 1; /* in sectors */ } void warn_cylinders(void) { - if (!sun_label && cylinders > 1024 && !nowarn) - fprintf(stderr, - "The number of cylinders for this disk is set to %d.\n" - "This is larger than 1024, and may cause " - "problems with:\n" - "1) software that runs at boot time (e.g., LILO)\n" - "2) booting and partitioning software from other OSs\n" - " (e.g., DOS FDISK, OS/2 FDISK)\n", + if (!sun_label && !sgi_label && cylinders > 1024 && !nowarn) + fprintf(stderr, "\n\ +The number of cylinders for this disk is set to %d.\n\ +There is nothing wrong with that, but this is larger than 1024,\n\ +and could in certain setups cause problems with:\n\ +1) software that runs at boot time (e.g., LILO)\n\ +2) booting and partitioning software from other OSs\n\ + (e.g., DOS FDISK, OS/2 FDISK)\n", cylinders); } @@ -537,23 +572,23 @@ void read_extended(struct partition *p) if (!extended_offset) extended_offset = get_start_sect(p); if (ext2_llseek(fd, (ext2_loff_t)offsets[partitions] - * SECTOR_SIZE, SEEK_SET) < 0) + * sector_size, SEEK_SET) < 0) fatal(unable_to_seek); - if (!(buffers[partitions] = (char *) malloc(SECTOR_SIZE))) + if (!(buffers[partitions] = (char *) malloc(sector_size))) fatal(out_of_memory); - if (SECTOR_SIZE != read(fd, buffers[partitions], SECTOR_SIZE)) + if (sector_size != read(fd, buffers[partitions], sector_size)) fatal(unable_to_read); part_table[partitions] = ext_pointers[partitions] = NULL; q = p = offset(buffers[partitions], 0); for (i = 0; i < 4; i++, p++) { - if (IS_EXTENDED (p->sys_ind)) + if (IS_EXTENDED (p->sys_ind)) { if (ext_pointers[partitions]) fprintf(stderr, "Warning: extra link " "pointer in partition table " "%d\n", partitions + 1); else ext_pointers[partitions] = p; - else if (p->sys_ind) + } else if (p->sys_ind) { if (part_table[partitions]) fprintf(stderr, "Warning: ignoring extra data " @@ -561,15 +596,18 @@ void read_extended(struct partition *p) partitions + 1); else part_table[partitions] = p; + } } - if (!part_table[partitions]) + if (!part_table[partitions]) { if (q != ext_pointers[partitions]) part_table[partitions] = q; else part_table[partitions] = q + 1; - if (!ext_pointers[partitions]) + } + if (!ext_pointers[partitions]) { if (q != part_table[partitions]) ext_pointers[partitions] = q; else ext_pointers[partitions] = q + 1; + } p = ext_pointers[partitions++]; } } @@ -583,6 +621,9 @@ void create_doslabel(void) "until you decide to write them. After that, of course, the previous\n" "content won't be recoverable.\n\n"); + sun_nolabel(); /* otherwise always recognised as sun */ + sgi_nolabel(); /* otherwise always recognised as sgi */ + write_part_table_flag(buffer); for (i = 0; i < 4; i++) clear_partition(part_table[i]); @@ -599,10 +640,11 @@ void create_doslabel(void) */ int get_boot(enum action what) { - int i; + int i, sec_fac; struct hd_geometry geometry; partitions = 4; + sec_fac = sector_size / 512; if (what == create_empty) goto got_table; /* skip reading disk */ @@ -614,11 +656,9 @@ int get_boot(enum action what) printf("You will not be able to write the partition table.\n"); } -#if defined(sparc) guess_device_type(fd); -#endif - if (SECTOR_SIZE != read(fd, buffer, SECTOR_SIZE)) + if (sector_size != read(fd, buffer, sector_size)) fatal(unable_to_read); #ifdef HDIO_REQ @@ -629,12 +669,14 @@ int get_boot(enum action what) heads = geometry.heads; sectors = geometry.sectors; cylinders = geometry.cylinders; + cylinders /= sec_fac; /* do not round up */ if (dos_compatible_flag) sector_offset = sectors; } else { if (!ioctl(fd, BLKGETSIZE, §ors)) { heads = 1; cylinders = 1; + sectors /= sec_fac; } else { heads = cylinders = sectors = 0; } @@ -643,17 +685,21 @@ int get_boot(enum action what) got_table: -#if defined(sparc) if (check_sun_label()) return 0; -#endif + + if (check_sgi_label()) + return 0; + + if (check_aix_label()) + return 0; if (!valid_part_table_flag(buffer)) { switch(what) { case fdisk: fprintf(stderr, "Device contains neither a valid DOS partition" - " table, nor Sun disklabel\n"); + " table, nor Sun or SGI disklabel\n"); #ifdef __sparc__ create_sunlabel(); #else @@ -676,12 +722,12 @@ got_table: warn_geometry(); for (i = 0; i < 4; i++) - if(IS_EXTENDED (part_table[i]->sys_ind)) + if(IS_EXTENDED (part_table[i]->sys_ind)) { if (partitions != 4) fprintf(stderr, "Ignoring extra extended " "partition %d\n", i + 1); else read_extended(part_table[ext_index = i]); - + } for (i = 3; i < partitions; i++) if (!valid_part_table_flag(buffers[i])) { fprintf(stderr, @@ -694,17 +740,20 @@ got_table: return 0; } -int read_line(void) +/* read line; return 0 or first char */ +int +read_line(void) { + line_ptr = line_buffer; if (!fgets(line_buffer, LINE_LENGTH, stdin)) return 0; - line_ptr = line_buffer; while (*line_ptr && !isgraph(*line_ptr)) line_ptr++; return *line_ptr; } -char read_char(char *mesg) +char +read_char(char *mesg) { do { fputs(mesg, stdout); @@ -712,17 +761,19 @@ char read_char(char *mesg) return *line_ptr; } -char read_chars(char *mesg) +char +read_chars(char *mesg) { fputs(mesg, stdout); if (!read_line()) { *line_ptr = '\n'; - return '\n'; - } else - return *line_ptr; + line_ptr[1] = 0; + } + return *line_ptr; } -int read_hex(struct systypes *sys) +int +read_hex(struct systypes *sys) { int hex; @@ -742,75 +793,80 @@ int read_hex(struct systypes *sys) } } - -uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg) +/* + * Print the message MESG, then read an integer between LOW and HIGH. + * If the user hits Enter, DFLT is returned. + * Answers like +10 are interpreted as offsets from BASE. + * + * There is no default if DFLT is not between LOW and HIGH. + */ +uint +read_int(uint low, uint dflt, uint high, uint base, char *mesg) { - uint i, use_default = 1; - char ms[70]; - - switch(base) { - case lower: - sprintf(ms, "%s ([%d]-%d): ", mesg, low, high); - break; - case upper: - sprintf(ms, "%s (%d-[%d]): ", mesg, low, high); - break; - case deflt: - sprintf(ms, "%s (%d-[%d]-%d): ", mesg, low, dflt, high); - break; - default: - sprintf(ms, "%s (%d-%d): ", mesg, low, high); - break; + uint i; + int default_ok = 1; + static char *ms = NULL; + static int mslen = 0; + + if (!ms || strlen(mesg)+50 > mslen) { + mslen = strlen(mesg)+100; + if (!(ms = realloc(ms,mslen))) + fatal(out_of_memory); } + if (dflt < low || dflt > high) + default_ok = 0; + + if (default_ok) + sprintf(ms, "%s (%d-%d, default %d): ", mesg, low, high, dflt); + else + sprintf(ms, "%s (%d-%d): ", mesg, low, high); + while (1) { - if (base == deflt) { - while (read_chars(ms) != '\n' && !isdigit(*line_ptr) - && *line_ptr != '-' && *line_ptr != '+') - continue; - if (*line_ptr == '\n') - return dflt; - } else { - while (!isdigit(read_char(ms)) - && *line_ptr != '-' && *line_ptr != '+') - continue; - } + int use_default = default_ok; + + /* ask question and read answer */ + while (read_chars(ms) != '\n' && !isdigit(*line_ptr) + && *line_ptr != '-' && *line_ptr != '+') + continue; + if (*line_ptr == '+' || *line_ptr == '-') { - if (*line_ptr == '+') - ++line_ptr; - i = atoi(line_ptr); - while (isdigit(*line_ptr)) - { - line_ptr++; + i = atoi(line_ptr+1); + if (*line_ptr == '-') + i = -i; + while (isdigit(*++line_ptr)) use_default = 0; - } switch (*line_ptr) { case 'c': - case 'C': if (!unit_flag) + case 'C': + if (!unit_flag) i *= heads * sectors; break; case 'k': - case 'K': i *= 2; + case 'K': + i *= 2; + i /= (sector_size / 512); i /= display_factor; break; case 'm': - case 'M': i *= 2048; + case 'M': + i *= 2048; + i /= (sector_size / 512); i /= display_factor; break; - default: break; - } - switch(base) { - case lower: i += low; break; - case upper: i += high; break; - case deflt: i += dflt; break; - case ignore: + case 'g': + case 'G': + i *= 2048000; + i /= (sector_size / 512); + i /= display_factor; + break; + default: + break; } - } - else - { + i += base; + } else { i = atoi(line_ptr); - while (isdigit(*line_ptr)) - { + while (isdigit(*line_ptr)) { line_ptr++; use_default = 0; } @@ -827,19 +883,14 @@ uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg) int get_partition(int warn, int max) { - /* - * try to pick a default least likely to do damage, - * in case luser just types a newline - */ - int i = read_int(1, max, max, ignore, "Partition number") - 1; + int i = read_int(1, 0, max, 0, "Partition number") - 1; if (warn && ( - (!sun_label && !part_table[i]->sys_ind) -#if defined(sparc) + (!sun_label && !sgi_label && !part_table[i]->sys_ind) || (sun_label && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id)) -#endif + || (sgi_label && (!sgi_get_num_sectors(i))) )) fprintf(stderr, "Warning: partition %d has empty type\n", i+1); return i; } @@ -897,12 +948,15 @@ void delete_partition(int i) if (warn_geometry()) return; changed[i] = 1; -#if defined(sparc) + if (sun_label) { sun_delete_partition(i); return; } -#endif + if (sgi_label) { + sgi_delete_partition(i); + return; + } if (i < 4) { if (IS_EXTENDED (p->sys_ind) && i == ext_index) { while (partitions > 4) @@ -961,30 +1015,22 @@ void change_sysid(void) int i = get_partition(0, partitions), sys, origsys; struct partition *p = part_table[i]; -#if defined(sparc) - if (sun_label) - sys = sunlabel->infos[i].id; - else -#endif - sys = p->sys_ind; - origsys = sys; + origsys = sys = get_sysid(i); - if (!sys) + if (!sys && !sgi_label) printf("Partition %d does not exist yet!\n", i + 1); else while (1) { - if (!sun_label) - sys = read_hex (sys_types); -#if defined(sparc) - else - sys = read_hex (sun_sys_types); -#endif - - if (!sys) { - delete_partition(i); - break; + sys = read_hex (get_sys_types()); + + if (!sys && !sgi_label) { + printf("Type 0 means free space to many systems\n" + "(but not to Linux). Having partitions of\n" + "type 0 is probably unwise. You can delete\n" + "a partition using the `d' command.\n"); + /* break; */ } - if (!sun_label) { + if (!sun_label && !sgi_label) { if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) { printf("You cannot change a partition into" " an extended one or vice versa\n" @@ -994,20 +1040,26 @@ void change_sysid(void) } if (sys < 256) { -#if defined(sparc) if (sun_label && i == 2 && sys != WHOLE_DISK) printf("Consider leaving partition 3 " "as Whole disk (5),\n" "as SunOS/Solaris expects it and " - "even Linux likes it.\n"); -#endif + "even Linux likes it.\n\n"); + if (sgi_label && ((i == 10 && sys != ENTIRE_DISK) + || (i == 8 && sys != 0))) + printf("Consider leaving partition 9 " + "as volume header (0),\nand " + "partition 11 as entire volume (6)" + "as IRIX expects it.\n\n"); if (sys == origsys) break; -#if defined(sparc) - if (sunlabel) { + + if (sun_label) { sun_change_sysid(i, sys); } else -#endif + if (sgi_label) { + sgi_change_sysid(i, sys); + } else part_table[i]->sys_ind = sys; printf ("Changed system type of partition %d " "to %x (%s)\n", i + 1, sys, @@ -1096,46 +1148,65 @@ static void check_consistency(struct partition *p, int partition) } } +void list_disk_geometry(void) +{ + printf("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " + "%ss of %d * %d bytes\n\n", disk_device, heads, sectors, + cylinders, str_units(), display_factor, sector_size); +} + void list_table(int xtra) { struct partition *p; char *type; + int digit_last = 0; int i, w; -#if defined(sparc) - if (sun_label) + if (sun_label) { sun_list_table(xtra); - return; -#endif + return; + } + + if (sgi_label) { + sgi_list_table(xtra); + return; + } w = strlen(disk_device); + /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3, + but if the device name ends in a digit, say /dev/foo1, + then the partition is called /dev/foo1p3. */ + if (isdigit(disk_device[w-1])) + digit_last = 1; + + list_disk_geometry(); - printf("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " - "%ss of %d * 512 bytes\n\n", disk_device, heads, sectors, - cylinders, str_units(), display_factor); if (w < 5) w = 5; - printf("%*s Boot %s Start End Blocks Id System\n", - w + 1, "Device", show_begin ? " Begin " : " "); + printf("%*s Boot Start End Blocks Id System\n", + (digit_last ? w + 2 : w + 1), "Device"); for (i = 0 ; i < partitions; i++) { if ((p = part_table[i])->sys_ind) { unsigned int psects = get_nr_sects(p); + unsigned int pblocks = psects; + unsigned int podd = 0; + + if (sector_size < 1024) { + pblocks /= (1024 / sector_size); + podd = psects % (1024 / sector_size); + } + if (sector_size > 1024) + pblocks *= (sector_size / 1024); printf( - show_begin - ? "%*s%-2d %c%9d%9d%9d%9d%c %2x %s\n" - : "%*s%-2d %c%c%9d%9d%9d%c %2x %s\n", -/* device */ w, disk_device, i+1, + "%*s%s%-2d %c %9ld %9ld %9ld%c %2x %s\n", +/* device */ w, disk_device, (digit_last ? "p" : ""), i+1, /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG ? '*' : '?', - show_begin ? -/* begin */ cround(rounded( calculate(p->head, p->sector, p->cyl), - get_start_sect(p) + offsets[i])) - : ' ', -/* start */ cround(get_start_sect(p) + offsets[i]), -/* end */ cround(get_start_sect(p) + offsets[i] + psects +/* start */ (long) cround(get_start_sect(p) + offsets[i]), +/* end */ (long) cround(get_start_sect(p) + offsets[i] + psects - (psects ? 1 : 0)), -/* odd flag on end */ psects / 2, (psects & 1) ? '+' : ' ', +/* odd flag on end */ (long) pblocks, podd ? '+' : ' ', /* type id */ p->sys_ind, /* type name */ (type = partition_type(p->sys_ind)) ? type : "Unknown"); @@ -1170,39 +1241,29 @@ void x_list_table(int extend) } } -void check_bounds(uint *first, uint *last) +void fill_bounds(uint *first, uint *last) { int i; - uint max = 0xffffffff; /* used to be 256 * 63 * 1024 - but that made it impossible to add a - partition crossing cylinder 8064 */ struct partition *p = part_table[0]; for (i = 0; i < partitions; p = part_table[++i]) { if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) { - first[i] = max; + first[i] = 0xffffffff; last[i] = 0; } else { - first[i] = rounded(calculate(p->head, p->sector, - p->cyl), get_start_sect(p) + offsets[i]); - last[i] = get_start_sect(p) + offsets[i] + - get_nr_sects(p) - 1; + first[i] = get_start_sect(p) + offsets[i]; + last[i] = first[i] + get_nr_sects(p) - 1; } } } void check(int n, uint h, uint s, uint c, uint start) { - uint total, real_s, real_c, i; + uint total, real_s, real_c; real_s = sector(s) - 1; real_c = cylinder(s, c); total = (real_c * sectors + real_s) * heads + h; - if (full_bits) - while ((i = total + full_bits) <= start) { - real_c += 1024; - total = i; - } if (!total) fprintf(stderr, "Warning: partition %d contains sector 0\n", n); if (h >= heads) @@ -1225,20 +1286,24 @@ void check(int n, uint h, uint s, uint c, uint start) void verify(void) { int i, j; - uint total = 1, - first[partitions], last[partitions]; + uint total = 1; + uint first[partitions], last[partitions]; struct partition *p = part_table[0]; if (warn_geometry()) return; -#if defined(sparc) - if (sun_label) + if (sun_label) { verify_sun(); - return; -#endif + return; + } + + if (sgi_label) { + verify_sgi(1); + return; + } - check_bounds(first, last); + fill_bounds(first, last); for (i = 0; i < partitions; p = part_table[++i]) if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { check_consistency(p, i); @@ -1299,7 +1364,7 @@ void add_partition(int n, int sys) "it before re-adding it.\n", n + 1); return; } - check_bounds(first, last); + fill_bounds(first, last); if (n < 4) { start = sector_offset; limit = heads * sectors * cylinders - 1; @@ -1339,7 +1404,7 @@ void add_partition(int n, int sys) uint i; i = start; start = read_int(cround(i), cround(i), cround(limit), - ignore, mesg); + 0, mesg); if (unit_flag) { start = (start - 1) * display_factor; if (start < i) start = i; @@ -1370,7 +1435,7 @@ void add_partition(int n, int sys) sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); stop = read_int(cround(start), cround(limit), cround(limit), - lower, mesg); + cround(start), mesg); if (unit_flag) { stop = stop * display_factor - 1; if (stop >limit) @@ -1384,7 +1449,7 @@ void add_partition(int n, int sys) ext_index = n; offsets[4] = extended_offset = start; ext_pointers[n] = p; - if (!(buffers[4] = calloc(1, SECTOR_SIZE))) + if (!(buffers[4] = calloc(1, sector_size))) fatal(out_of_memory); part_table[4] = offset(buffers[4], 0); ext_pointers[4] = part_table[4] + 1; @@ -1407,7 +1472,7 @@ void add_partition(int n, int sys) void add_logical(void) { if (partitions > 5 || part_table[4]->sys_ind) { - if (!(buffers[partitions] = calloc(1, SECTOR_SIZE))) + if (!(buffers[partitions] = calloc(1, sector_size))) fatal(out_of_memory); part_table[partitions] = offset(buffers[partitions], 0); ext_pointers[partitions] = part_table[partitions] + 1; @@ -1424,11 +1489,15 @@ void new_partition(void) if (warn_geometry()) return; -#if defined(sparc) - if (sun_label) + if (sun_label) { add_sun_partition(get_partition(0, partitions), LINUX_NATIVE); - return; -#endif + return; + } + + if (sgi_label) { + sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE); + return; + } if (partitions >= MAXIMUM_PARTS) { printf("The maximum number of partitions has been created\n"); @@ -1437,13 +1506,13 @@ void new_partition(void) for (i = 0; i < 4; i++) free_primary += !part_table[i]->sys_ind; - if (!free_primary) + if (!free_primary) { if (extended_offset) add_logical(); else printf("You must delete some partition and add " "an extended partition first\n"); - else { + } else { char c, line[LINE_LENGTH]; sprintf(line, "Command action\n %s\n p primary " "partition (1-4)\n", extended_offset ? @@ -1475,24 +1544,25 @@ void write_table(void) int i, error = 0; changed[3] = changed[0] || changed[1] || changed[2] || changed[3]; - if (!sun_label) { + if (!sun_label && !sgi_label) { for (i = 3; i < partitions; i++) { if (changed[i]) { write_part_table_flag(buffers[i]); if (ext2_llseek(fd, (ext2_loff_t)offsets[i] - * SECTOR_SIZE, SEEK_SET) < 0) + * sector_size, SEEK_SET) < 0) fatal(unable_to_seek); - if (write(fd, buffers[i], SECTOR_SIZE) != SECTOR_SIZE) + if (write(fd, buffers[i], sector_size) != sector_size) fatal(unable_to_write); } } - } else { -#if defined(sparc) + } else if (sgi_label) { + /* no test on change? the printf below might be mistaken */ + sgi_write_table(); + } else if (sun_label) { if (changed[3] || changed[4] || changed[5] || changed[6] || changed[7]) { sun_write_table(); } -#endif } printf("The partition table has been altered!\n\n"); @@ -1523,7 +1593,7 @@ void write_table(void) "system to ensure the partition table is updated.\n", error, strerror(error)); - if (!sun_label) + if (!sun_label && !sgi_label) printf( "\nWARNING: If you have created or modified any DOS 6.x\n" "partitions, please see the fdisk manual page for additional\n" @@ -1538,7 +1608,7 @@ void print_buffer(char buffer[]) int i, l; - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { + for (i = 0, l = 0; i < sector_size; i++, l++) { if (l == 0) printf("0x%03X:", i); printf(" %02X", (unsigned char) buffer[i]); @@ -1557,7 +1627,7 @@ void print_raw(void) int i; printf("Device: %s\n", disk_device); - if (sun_label) + if (sun_label || sgi_label) print_buffer(buffer); else for (i = 3; i < partitions; i++) print_buffer(buffers[i]); @@ -1574,11 +1644,10 @@ void move_begin(int i) printf("Partition %d has no data area\n", i + 1); return; } - first = rounded(calculate(p->head, p->sector, p->cyl), - get_start_sect(p) + offsets[i]); + first = get_start_sect(p) + offsets[i]; new = read_int(first, first, get_start_sect(p) + get_nr_sects(p) + offsets[i] - 1, - lower, "New beginning of data") - offsets[i]; + first, "New beginning of data") - offsets[i]; if (new != get_nr_sects(p)) { first = get_nr_sects(p) + get_start_sect(p) - new; @@ -1593,42 +1662,40 @@ void xselect(void) while(1) { putchar('\n'); switch (tolower(read_char("Expert command (m for help): "))) { -#if defined(sparc) case 'a': if (sun_label) sun_set_alt_cyl(); break; -#endif case 'b': - if (!sun_label) + if (!sun_label && !sgi_label) move_begin(get_partition(0, partitions)); break; case 'c': cylinders = read_int(1, cylinders, 65535, - deflt, "Number of cylinders"); -#if defined(sparc) + 0, "Number of cylinders"); if (sun_label) sun_set_ncyl(cylinders); -#endif warn_cylinders(); break; case 'd': print_raw(); break; case 'e': - if (!sun_label) - x_list_table(1); -#if defined(sparc) - else + if (sgi_label) + sgi_set_xcyl(); + else if (sun_label) sun_set_xcyl(); -#endif + else + x_list_table(1); + break; + case 'g': + create_sgilabel(); break; case 'h': - heads = read_int(1, heads, 256, deflt, + heads = read_int(1, heads, 256, 0, "Number of heads"); update_units(); break; -#if defined(sparc) case 'i': if (sun_label) sun_set_ilfact(); @@ -1637,13 +1704,10 @@ void xselect(void) if (sun_label) sun_set_rspeed(); break; -#endif case 'p': -#if defined(sparc) if (sun_label) list_table(1); else -#endif x_list_table(0); break; case 'q': @@ -1652,7 +1716,7 @@ void xselect(void) case 'r': return; case 's': - sectors = read_int(1, sectors, 63, deflt, + sectors = read_int(1, sectors, 63, 0, "Number of sectors"); if (dos_compatible_flag) { sector_offset = sectors; @@ -1668,12 +1732,10 @@ void xselect(void) case 'w': write_table(); /* does not return */ break; -#if defined(sparc) case 'y': if (sun_label) sun_set_pcylcount(); break; -#endif default: xmenu(); } @@ -1693,6 +1755,8 @@ is_ide_cdrom(char *device) { char buf[100]; struct stat statbuf; + if (strncmp("/dev/hd", device, 7)) + return 0; sprintf(buf, "/proc/ide/%s/media", device+5); procf = fopen(buf, "r"); if (procf != NULL && fgets(buf, sizeof(buf), procf)) @@ -1715,10 +1779,11 @@ void try(char *device, int user_specified) return; if ((fd = open(disk_device, type_open)) >= 0) { if (get_boot(try_only) < 0) { + list_disk_geometry(); if (btrydev(device) < 0) fprintf(stderr, - "Disk doesn't contain a valid " - "partition table\n"); + "Disk %s doesn't contain a valid " + "partition table\n", device); close(fd); } else { close(fd); @@ -1741,7 +1806,8 @@ void try(char *device, int user_specified) void dummy(int *kk) {} -void main(int argc, char **argv) +int +main(int argc, char **argv) { int i, j, s, c; int optl = 0, opts = 0; @@ -1751,14 +1817,18 @@ void main(int argc, char **argv) /* * Calls: * fdisk -v - * fdisk -l [-b] [-u] [device] ... + * fdisk -l [-b sectorsize] [-u] [device] ... * fdisk -s [partition] ... - * fdisk [-b] [-u] [device] + * fdisk [-b sectorsize] [-u] [device] */ - while ((c = getopt(argc, argv, "blsuv")) != EOF) { + while ((c = getopt(argc, argv, "b:lsuv")) != EOF) { switch (c) { case 'b': - show_begin = 1; + sector_size = atoi(optarg); + if (sector_size != 512 && sector_size != 1024 && + sector_size != 2048) + fatal(usage); + sector_offset = 2; break; case 'l': optl = 1; @@ -1770,7 +1840,7 @@ void main(int argc, char **argv) unit_flag = 0; break; case 'v': - printf("fdisk v" VERSION "\n"); + printf("fdisk v" UTIL_LINUX_VERSION "\n"); exit(0); default: fatal(usage); @@ -1801,18 +1871,27 @@ void main(int argc, char **argv) try("/dev/sdf", 0); try("/dev/sdg", 0); try("/dev/sdh", 0); - try("/dev/eda", 0); + try("/dev/eda", 0); /* PS/2 ESDI drives */ try("/dev/edb", 0); try("/dev/edc", 0); try("/dev/edd", 0); + try("/dev/rd/c0d0", 0); /* DAC960 RAID disks */ + try("/dev/rd/c0d1", 0); + try("/dev/rd/c0d2", 0); + try("/dev/rd/c0d3", 0); + try("/dev/rd/c0d4", 0); + try("/dev/rd/c0d5", 0); + try("/dev/rd/c0d6", 0); + try("/dev/rd/c0d7", 0); } exit(0); } if (opts) { - /* Silly assumptions here about device naming */ + /* Very silly assumptions here about device naming */ + /* All this junk will disappear again */ nowarn = 1; - disk_device = (char *) malloc(9); + disk_device = (char *) malloc(16); type_open = O_RDONLY; opts = argc - optind; @@ -1821,13 +1900,24 @@ void main(int argc, char **argv) for (j = optind; j < argc; j++) { part = argv[j]; - if (strlen(part) < 9) - fatal(usage); - if (!(i = atoi(part + 8))) - fatal(usage); - i--; /* count from 0 */ - strncpy(disk_device, part, 8); - disk_device[8] = 0; + if (strncmp(part, "/dev/rd/", 8) == 0) { + char *p = strrchr(part, 'p'); + if (p == NULL) + fatal(usage); + if (!(i = atoi(p + 1))) + fatal(usage); + i--; /* count from 0 */ + *p = '\0'; + strcpy(disk_device, part); + } else { + if (strlen(part) < 9) + fatal(usage); + if (!(i = atoi(part + 8))) + fatal(usage); + i--; /* count from 0 */ + strncpy(disk_device, part, 8); + disk_device[8] = 0; + } if ((fd = open(disk_device, type_open)) < 0) fatal(unable_to_open); close(fd); @@ -1869,37 +1959,50 @@ void main(int argc, char **argv) putchar('\n'); switch (tolower(read_char("Command (m for help): "))) { case 'a': -#if defined(sparc) if (sun_label) toggle_sunflags(get_partition(1, partitions), 0x01); else -#endif - toggle_active(get_partition(1, partitions)); + if (sgi_label) + sgi_set_bootpartition( + get_partition(1, partitions)); + else + toggle_active(get_partition(1, partitions)); break; case 'b': - bselect(); + if (sgi_label) { + printf("\nThe current boot file is: %s\n", + sgi_get_bootfile()); + if (read_chars("Please enter the name of the " + "new boot file: ") == '\n') + printf("Boot file unchanged\n"); + else + sgi_set_bootfile(line_ptr); + } else + bselect(); break; case 'c': -#if defined(sparc) if (sun_label) toggle_sunflags(get_partition(1, partitions), 0x10); else -#endif - toggle_dos(); + if (sgi_label) + sgi_set_swappartition( + get_partition(1, partitions)); + else + toggle_dos(); break; case 'd': delete_partition( get_partition(1, partitions)); break; - case 'l': -#if defined(sparc) - if (sun_label) - list_types(sun_sys_types); + case 'i': + if (sgi_label) + create_sgiinfo(); else -#endif - list_types(sys_types); + menu(); + case 'l': + list_types(get_sys_types()); break; case 'n': new_partition(); @@ -1913,11 +2016,9 @@ void main(int argc, char **argv) case 'q': close(fd); exit(0); -#if defined(sparc) case 's': create_sunlabel(); break; -#endif case 't': change_sysid(); break; @@ -1931,10 +2032,15 @@ void main(int argc, char **argv) write_table(); /* does not return */ break; case 'x': - xselect(); + if( sgi_label ) { + fprintf(stderr, + "\n\tSorry, no experts menu for SGI " + "partition tables available.\n\n"); + } else + xselect(); break; default: menu(); } } + return 0; } - diff --git a/disk-utils/fdisk.h b/fdisk/fdisk.h similarity index 73% rename from disk-utils/fdisk.h rename to fdisk/fdisk.h index 11f529d4..080515e5 100644 --- a/disk-utils/fdisk.h +++ b/fdisk/fdisk.h @@ -2,9 +2,23 @@ fdisk.h */ -#define SECTOR_SIZE 512 +#define DEFAULT_SECTOR_SIZE 512 +#define MAX_SECTOR_SIZE 2048 +#define SECTOR_SIZE 512 /* still used in BSD code */ #define MAXIMUM_PARTS 60 +#define ACTIVE_FLAG 0x80 + +#define EXTENDED 0x05 +#define WIN98_EXTENDED 0x0f +#define LINUX_PARTITION 0x81 +#define LINUX_SWAP 0x82 +#define LINUX_NATIVE 0x83 +#define LINUX_EXTENDED 0x85 + +#define IS_EXTENDED(i) \ + ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) + #define SIZE(a) (sizeof(a)/sizeof((a)[0])) #define cround(n) (((n) + display_factor * unit_flag) / display_factor) @@ -33,9 +47,7 @@ struct partition { }; enum failure {usage, unable_to_open, unable_to_read, unable_to_seek, - unable_to_write, out_of_memory}; - -enum offset {ignore, lower, deflt, upper}; + unable_to_write, out_of_memory, no_partition, no_device}; enum action {fdisk, require, try_only, create_empty}; @@ -59,14 +71,15 @@ extern void list_types(struct systypes *sys); extern int read_line (void); extern char read_char(char *mesg); extern int read_hex(struct systypes *sys); -uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg); +uint read_int(uint low, uint dflt, uint high, uint base, char *mesg); extern char *const str_units(void); extern unsigned int get_start_sect(struct partition *p); extern unsigned int get_nr_sects(struct partition *p); -/* prototypes for fdisklabel.c */ +/* prototypes for fdiskbsdlabel.c */ extern void bselect(void); extern int btrydev (char * dev); -/* prototypes for fdisksunlabel.c */ +/* prototypes for fdisksgilabel.c */ +extern int valid_part_table_flag(unsigned char *b); diff --git a/fdisk/fdiskaixlabel.c b/fdisk/fdiskaixlabel.c new file mode 100644 index 00000000..848a6ece --- /dev/null +++ b/fdisk/fdiskaixlabel.c @@ -0,0 +1,64 @@ +#include /* stderr */ +#include /* uint */ +#include /* strstr */ +#include /* write */ + +#include + +#include "fdisk.h" +#include "fdiskaixlabel.h" + +static int other_endian = 0; +static short volumes=1; + +/* + * only dealing with free blocks here + */ + +void +aix_info( void ) +{ + printf( + "\n\tThere is a valid AIX label on this disk.\n" + "\tUnfortunately Linux cannot handle these\n" + "\tdisks at the moment. Nevertheless some\n" + "\tadvice:\n" + "\t1. fdisk will destroy its contents on write.\n" + "\t2. Be sure that this disk is NOT a still vital\n" + "\t part of a volume group. (Otherwise you may\n" + "\t erase the other disks as well, if unmirrored.)\n" + "\t3. Before deleting this physical volume be sure\n" + "\t to remove the disk logically from your AIX\n" + "\t machine. (Otherwise you become an AIXpert).\n" + ); +} + +void +aix_nolabel( void ) +{ + aixlabel->magic = 0; + aix_label = 0; + partitions = 4; + memset( buffer, 0, sizeof(buffer) ); /* avoid fdisk cores */ + return; +} + +int +check_aix_label( void ) +{ + if (aixlabel->magic != AIX_LABEL_MAGIC && + aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) { + aix_label = 0; + other_endian = 0; + return 0; + } + other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED); + update_units(); + aix_label = 1; + partitions= 1016; + volumes = 15; + aix_info(); + aix_nolabel(); /* %% */ + aix_label = 1; /* %% */ + return 1; +} diff --git a/fdisk/fdiskaixlabel.h b/fdisk/fdiskaixlabel.h new file mode 100644 index 00000000..fd95bc01 --- /dev/null +++ b/fdisk/fdiskaixlabel.h @@ -0,0 +1,34 @@ +#include /* for __u32 etc */ +/* + * Copyright (C) Andreas Neuper, Sep 1998. + * This file may be redistributed under + * the terms of the GNU Public License. + */ + +typedef struct { + unsigned int magic; /* expect AIX_LABEL_MAGIC */ + unsigned int fillbytes1[124]; + unsigned int physical_volume_id; + unsigned int fillbytes2[124]; +} aix_partition; + +#define AIX_LABEL_MAGIC 0xc9c2d4c1 +#define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9 +#define AIX_INFO_MAGIC 0x00072959 +#define AIX_INFO_MAGIC_SWAPPED 0x59290700 + +/* fdisk.c */ +#define aixlabel ((aix_partition *)buffer) +extern char buffer[MAX_SECTOR_SIZE]; +extern char changed[MAXIMUM_PARTS]; +extern uint heads, sectors, cylinders; +extern int show_begin; +extern int aix_label; +extern char *partition_type(unsigned char type); +extern void update_units(void); +extern char read_chars(char *mesg); + +/* fdiskaixlabel.c */ +extern struct systypes aix_sys_types[]; +extern void aix_nolabel( void ); +extern int check_aix_label( void ); diff --git a/disk-utils/fdisklabel.c b/fdisk/fdiskbsdlabel.c similarity index 96% rename from disk-utils/fdisklabel.c rename to fdisk/fdiskbsdlabel.c index d98d49d0..8edec233 100644 --- a/disk-utils/fdisklabel.c +++ b/fdisk/fdiskbsdlabel.c @@ -52,7 +52,7 @@ #include "fdisk.h" #define NETBSD_PARTITION 0xa5 #define DKTYPENAMES -#include "fdisklabel.h" +#include "fdiskbsdlabel.h" static void xbsd_delete_part (void); static void xbsd_new_part (void); @@ -118,20 +118,27 @@ bmenu (void) ); } +int +hidden(int type) { + return type ^ 0x10; +} + +int +is_netbsd_partition_type(int type) { + return (type == NETBSD_PARTITION || type == hidden(NETBSD_PARTITION)); +} + void -bselect (void) -{ +bselect (void) { #if defined (i386) || defined (sparc) int t, ss; for (t=0; t<4; t++) - if (part_table[t] -> sys_ind == NETBSD_PARTITION) - { + if (is_netbsd_partition_type(part_table[t] -> sys_ind)) { xbsd_part = part_table[t]; xbsd_part_index = t; ss = get_start_sect(xbsd_part); - if (ss == 0) - { + if (ss == 0) { fprintf (stderr, "Partition %s%d has invalid starting sector 0.\n", disk_device, t+1); return; @@ -144,9 +151,8 @@ bselect (void) break; } - if (t == 4) - { - printf ("There is no NetBSD partition on %s.\n", disk_device); + if (t == 4) { + printf ("There is no *BSD partition on %s.\n", disk_device); return; } @@ -234,16 +240,18 @@ xbsd_new_part (void) #if defined (i386) || defined (sparc) begin = get_start_sect(xbsd_part); end = begin + get_nr_sects(xbsd_part) - 1; -#elif defined (__alpha__) +#elif defined (__alpha__) || defined (__powerpc__) begin = 0; end = xbsd_dlabel.d_secperunit; #endif sprintf (mesg, "First %s", str_units()); - begin = read_int (cround (begin), cround (begin), cround (end), ignore, mesg); + begin = read_int (cround (begin), cround (begin), cround (end), + 0, mesg); sprintf (mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); - end = read_int (cround (begin), cround (end), cround (end), ignore, mesg); + end = read_int (cround (begin), cround (end), cround (end), + cround (begin), mesg); if (unit_flag) { @@ -388,7 +396,7 @@ xbsd_create_disklabel (void) { #if defined (i386) || defined (sparc) if (xbsd_initlabel (xbsd_part, &xbsd_dlabel, xbsd_part_index) == 1) -#elif defined (__alpha__) +#elif defined (__alpha__) || defined (__powerpc__) if (xbsd_initlabel (NULL, &xbsd_dlabel, 0) == 1) #endif { @@ -519,6 +527,8 @@ xbsd_write_bootstrap (void) #if defined (i386) || defined (sparc) sector = get_start_sect(xbsd_part); +#elif defined (__powerpc__) + sector = 0; #elif defined (__alpha__) sector = 0; alpha_bootblock_checksum (buffer); @@ -718,7 +728,7 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) #if defined (i386) || defined (sparc) sector = get_start_sect(p) + BSD_LABELSECTOR; -#elif defined (__alpha__) +#elif defined (__alpha__) || defined (__powerpc__) sector = BSD_LABELSECTOR; #endif diff --git a/disk-utils/fdisklabel.h b/fdisk/fdiskbsdlabel.h similarity index 99% rename from disk-utils/fdisklabel.h rename to fdisk/fdiskbsdlabel.h index 06435f4d..b9f2c9c3 100644 --- a/disk-utils/fdisklabel.h +++ b/fdisk/fdiskbsdlabel.h @@ -46,7 +46,7 @@ #if defined (i386) || defined (sparc) #define BSD_LABELSECTOR 1 #define BSD_LABELOFFSET 0 -#elif defined (__alpha__) +#elif defined (__alpha__) || defined (__powerpc__) #define BSD_LABELSECTOR 0 #define BSD_LABELOFFSET 64 #else diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c new file mode 100644 index 00000000..42f7363e --- /dev/null +++ b/fdisk/fdisksgilabel.c @@ -0,0 +1,888 @@ +/* + * + * fdisksgilabel.c + * + * Copyright (C) Andreas Neuper, Sep 1998. + * This file may be modified and redistributed under + * the terms of the GNU Public License. + */ +#include /* stderr */ +#include /* uint */ +#include /* strstr */ +#include /* write */ +#include /* ioctl */ +#include /* stat */ +#include /* assert */ + +#include +#include /* FLOPPY_MAJOR */ +#include /* HDIO_GETGEO */ + +#include "fdisk.h" +#include "fdisksgilabel.h" + +static int other_endian = 0; +static int debug = 0; +static short volumes=1; + +/* + * only dealing with free blocks here + */ + +typedef struct { int first; int last; } freeblocks; +static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */ +void setfreelist( int i, int f, int l ) \ + { freelist[i].first = f; freelist[i].last = l; return; } +void add2freelist( int f, int l ) \ + { int i = 0; for( ; i<17 ; i++ ) { if(freelist[i].last==0) break; }\ + setfreelist( i, f, l ); return; } +void clearfreelist( void ) \ + { int i = 0; for( ; i<17 ; i++ ) { setfreelist( i, 0, 0 ); } return; } +int isinfreelist( int b ) \ + { int i = 0; for( ; i<17 ; i++ )\ + { if( ( freelist[i].first <= b ) && ( freelist[i].last >= b) )\ + { return freelist[i].last; } } return 0; } + /* return last vacant block of this stride (never 0). */ + /* the '>=' is not quite correct, but simplifies the code */ +/* + * end of free blocks section + */ + +struct systypes sgi_sys_types[] = { + {SGI_VOLHDR, "SGI volhdr"}, + {0x01, "SGI trkrepl"}, + {0x02, "SGI secrepl"}, + {SGI_SWAP, "SGI raw"}, + {0x04, "SGI bsd"}, + {0x05, "SGI sysv"}, + {ENTIRE_DISK, "SGI volume"}, + {SGI_EFS, "SGI efs"}, + {0x08, "SGI lvol"}, + {0x09, "SGI rlvol"}, + {0x0A, "SGI xfs"}, + {0x0B, "SGI xlvol"}, + {0x0C, "SGI rxlvol"}, + {LINUX_SWAP, "Linux swap"}, + {LINUX_NATIVE,"Linux native"}, + {0, NULL } +}; + +static inline unsigned short __swap16(unsigned short x) { + return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8); +} +static inline __u32 __swap32(__u32 x) { + return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24); +} + +static +int +sgi_get_nsect( void ) +{ + return SSWAP16(sgilabel->devparam.nsect); +} + +static +int +sgi_get_ntrks( void ) +{ + return SSWAP16(sgilabel->devparam.ntrks); +} + +#if 0 +static int +sgi_get_head_vol0( void ) +{ + return SSWAP16(sgilabel->devparam.head_vol0); +} + +static int +sgi_get_bytes( void ) +{ + return SSWAP16(sgilabel->devparam.bytes); +} +#endif + +static +int +sgi_get_pcylcount( void ) +{ + return SSWAP16(sgilabel->devparam.pcylcount); +} + +void +sgi_nolabel() +{ + sgilabel->magic = 0; + sgi_label = 0; + partitions = 4; +} + +unsigned int +two_s_complement_32bit_sum( + unsigned int* base, + int size /* in bytes */ ) +{ + int i=0; + unsigned int sum=0; + size = size / sizeof( unsigned int ); + for( i=0; i 512) { + fprintf(stderr, + "According to MIPS Computer Systems, Inc the " + "Label must not contain more than 512 bytes\n"); + exit(1); + } + + if (sgilabel->magic != SGI_LABEL_MAGIC && + sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) { + sgi_label = 0; + other_endian = 0; + return 0; + } + + other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED); + /* + * test for correct checksum + */ + if( two_s_complement_32bit_sum( (unsigned int*)sgilabel, + sizeof(*sgilabel) ) ) + { + fprintf( stderr, "Detected sgi disklabel with wrong checksum.\n" ); + } else + { + heads = sgi_get_ntrks(); + cylinders = sgi_get_pcylcount(); + sectors = sgi_get_nsect(); + } + update_units(); + sgi_label = 1; + partitions= 16; + volumes = 15; + return 1; +} + +void +sgi_list_table( int xtra ) +{ + int i, w; + char *type; + + w = strlen( disk_device ); + + if( xtra ) + { + printf( "\nDisk %s (SGI disk label): %d heads, %d sectors\n" + "%d cylinders, %d physical cylinders\n" + "%d extra sects/cyl, interleave %d:1\n" + "%s\n" + "Units = %ss of %d * 512 bytes\n\n", + disk_device, heads, sectors, cylinders, + SSWAP16(sgiparam.pcylcount), + SSWAP16(sgiparam.sparecyl), + SSWAP16(sgiparam.ilfact), + (char *)sgilabel, + str_units(), display_factor); + } else + { + printf( "\nDisk %s (SGI disk label): %d heads, %d sectors, %d cylinders\n" + "Units = %ss of %d * 512 bytes\n\n", + disk_device, heads, sectors, cylinders, + str_units(), display_factor ); + } + printf("----- partitions -----\n" + "%*s Info Start End Sectors Id System\n", + w + 1, "Device"); + for (i = 0 ; i < partitions; i++) + { + if( sgi_get_num_sectors(i) || debug ) + { + __u32 start = sgi_get_start_sector(i); + __u32 len = sgi_get_num_sectors(i); + printf( + "%*s%-2d %4s %9ld %9ld %9ld %2x %s\n", +/* device */ w, disk_device, i + 1, +/* flags */ (sgi_get_swappartition() == i) ? "swap" : +/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ", +/* start */ (long) scround(start), +/* end */ (long) scround(start+len)-1, +/* no odd flag on end */ (long) len, +/* type id */ sgi_get_sysid(i), +/* type name */ (type = partition_type(sgi_get_sysid(i))) + ? type : "Unknown"); + } + } + printf( "----- bootinfo -----\nBootfile: %s\n" + "----- directory entries -----\n", + sgilabel->boot_file ); + for (i = 0 ; i < volumes; i++) + { + if (sgilabel->directory[i].vol_file_size) + { + __u32 start = SSWAP32(sgilabel->directory[i].vol_file_start); + __u32 len = SSWAP32(sgilabel->directory[i].vol_file_size); + char*name = sgilabel->directory[i].vol_file_name; + printf("%2d: %-10s sector%5u size%8u\n", + i, name, (unsigned int) start, (unsigned int) len); + } + } +} + +int +sgi_get_start_sector( int i ) +{ + return SSWAP32(sgilabel->partitions[i].start_sector); +} + +int +sgi_get_num_sectors( int i ) +{ + return SSWAP32(sgilabel->partitions[i].num_sectors); +} + +int +sgi_get_sysid( int i ) +{ + return SSWAP32(sgilabel->partitions[i].id); +} + +int +sgi_get_bootpartition( void ) +{ + return SSWAP16(sgilabel->boot_part); +} + +int +sgi_get_swappartition( void ) +{ + return SSWAP16(sgilabel->swap_part); +} + +void +sgi_set_bootpartition( int i ) +{ + sgilabel->boot_part = SSWAP16(((short)i)); + return; +} + +int +sgi_get_lastblock( void ) +{ + return heads * sectors * cylinders; +} + +void +sgi_set_swappartition( int i ) +{ + sgilabel->swap_part = SSWAP16(((short)i)); + return; +} + +static int +sgi_check_bootfile( const char* aFile ) +{ + if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */ + { + printf( "\nInvalid Bootfile!\n" + "\tThe bootfile must be an absolute non-zero pathname,\n" + "\te.g. \"/unix\" or \"/unix.save\".\n" ); + return 0; + } else + if( strlen( aFile ) > 16 ) + { + printf( "\n\tName of Bootfile too long: 16 bytes maximum.\n" ); + return 0; + } else + if( aFile[0] != '/' ) + { + printf( "\n\tBootfile must have a fully qualified pathname.\n" ); + return 0; + } + if( strncmp( aFile, sgilabel->boot_file, 16 ) ) + { + printf( "\n\tBe aware, that the bootfile is not checked for existence.\n\t" + "SGI's default is \"/unix\" and for backup \"/unix.save\".\n" ); + /* filename is correct and did change */ + return 1; + } + return 0; /* filename did not change */ +} + +const char * +sgi_get_bootfile(void) { + return sgilabel->boot_file; +} + +void +sgi_set_bootfile( const char* aFile ) +{ + int i = 0; + if( sgi_check_bootfile( aFile ) ) + { + while( i<16 ) + { + if( (aFile[i] != '\n') /* in principle caught again by next line */ + && (strlen( aFile ) > i ) ) + sgilabel->boot_file[i] = aFile[i]; + else + sgilabel->boot_file[i] = 0; + i++; + } + printf( "\n\tBootfile is changed to \"%s\".\n", sgilabel->boot_file ); + } + return; +} + +void +create_sgiinfo( void ) +{ + /* I keep SGI's habit to write the sgilabel to the second block */ + sgilabel->directory[0].vol_file_start = SSWAP32( 2 ); + sgilabel->directory[0].vol_file_size = SSWAP32( sizeof( sgiinfo ) ); + strncpy( sgilabel->directory[0].vol_file_name, "sgilabel",8 ); + return; +} + +sgiinfo * fill_sgiinfo( void ); + +void +sgi_write_table( void ) +{ + sgilabel->csum = 0; + sgilabel->csum = SSWAP32( two_s_complement_32bit_sum( + (unsigned int*)sgilabel, + sizeof(*sgilabel) ) ); + assert( two_s_complement_32bit_sum( + (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 ); + if( lseek(fd, 0, SEEK_SET) < 0 ) + fatal(unable_to_seek); + if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE ) + fatal(unable_to_write); + if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) ) + { + /* + * keep this habbit of first writing the "sgilabel". + * I never tested whether it works without (AN 981002). + */ + sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */ + int infostartblock = SSWAP32( sgilabel->directory[0].vol_file_start ); + if( ext2_llseek(fd, (ext2_loff_t)infostartblock* + SECTOR_SIZE, SEEK_SET) < 0 ) + fatal(unable_to_seek); + if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE ) + fatal(unable_to_write); + free( info ); + } + return; +} + +static +int +compare_start( int*x, int*y ) +{ + /* + * sort according to start sectors + * and prefers largest partition: + * entry zero is entire disk entry + */ + int i = *x; + int j = *y; + int a = sgi_get_start_sector(i); + int b = sgi_get_start_sector(j); + int c = sgi_get_num_sectors(i); + int d = sgi_get_num_sectors(j); + if( a == b ) + { + return( d - c ); + } + return( a - b ); +} + +static +int +sgi_gaps() +{ + /* + * returned value is: + * = 0 : disk is properly filled to the rim + * < 0 : there is an overlap + * > 0 : there is still some vacant space + */ + return verify_sgi(0); +} + +int +verify_sgi( int verbose ) +{ + int Index[16]; /* list of valid partitions */ + int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */ + int compare_start();/* comparison function above */ + int entire = 0, i = 0; /* local counters */ + int start = 0; + int gap = 0; /* count unused blocks */ + int lastblock = sgi_get_lastblock(); + /* + */ + clearfreelist(); + for( i=0; i<16; i++ ) + { + if( sgi_get_num_sectors(i)!=0 ) + { + Index[sortcount++]=i; + if( sgi_get_sysid(i) == ENTIRE_DISK ) + { + if( entire++ == 1 ) + { + if(verbose) + printf("More than one entire disk entriy present.\n"); + } + } + } + } + if( sortcount == 0 ) + { + if(verbose) + printf("No partitions defined\n"); + return lastblock; + } + qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start ); + if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK ) + { + if( ( Index[0] != 10 ) && verbose ) + printf( "IRIX likes when Partition 11 covers the entire disk.\n" ); + if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose ) + printf( "The entire disk partition should start at block 0,\nnot " + "at diskblock %d.\n", sgi_get_start_sector(Index[0] ) ); + if(debug) /* I do not understand how some disks fulfil it */ + if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose ) + printf( "The entire disk partition is only %d diskblock large,\n" + "but the disk is %d diskblocks long.\n", + sgi_get_num_sectors( Index[0] ), lastblock ); + lastblock = sgi_get_num_sectors( Index[0] ); + } else + { + if( verbose ) + printf( "One Partition (#11) should cover the entire disk.\n" ); + if(debug>2) + printf( "sysid=%d\tpartition=%d\n", + sgi_get_sysid( Index[0] ), Index[0]+1 ); + } + for( i=1, start=0; i sgi_get_start_sector( Index[i] ) ) + { + if( verbose ) + printf( "The Partition %d and %d overlap by %d sectors.\n", + Index[i-1]+1, Index[i]+1, + start - sgi_get_start_sector( Index[i] ) ); + if( gap > 0 ) gap = -gap; + if( gap == 0 ) gap = -1; + } + if( start < sgi_get_start_sector( Index[i] ) ) + { + if( verbose ) + printf( "Unused gap of %8d sectors - sectors %8d-%d\n", + sgi_get_start_sector( Index[i] ) - start, + start, sgi_get_start_sector( Index[i] )-1 ); + gap += sgi_get_start_sector( Index[i] ) - start; + add2freelist( start, sgi_get_start_sector( Index[i] ) ); + } + start = sgi_get_start_sector( Index[i] ) + + sgi_get_num_sectors( Index[i] ); + if(debug>1) + { + if( verbose ) + printf( "%2d:%12d\t%12d\t%12d\n", Index[i], + sgi_get_start_sector(Index[i]), + sgi_get_num_sectors(Index[i]), + sgi_get_sysid(Index[i]) ); + } + } + if( ( start < lastblock ) ) + { + if( verbose ) + printf( "Unused gap of %8d sectors - sectors %8d-%d\n", + lastblock - start, start, lastblock-1 ); + gap += lastblock - start; + add2freelist( start, lastblock ); + } + /* + * Done with arithmetics + * Go for details now + */ + if( verbose ) + { + if( !sgi_get_num_sectors( sgi_get_bootpartition() ) ) + { + printf( "\nThe boot partition does not exist.\n" ); + } + if( !sgi_get_num_sectors( sgi_get_swappartition() ) ) + { + printf( "\nThe swap partition does not exist.\n" ); + } else + if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP ) + && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) ) + { + printf( "\nThe swap partition has no swap type.\n" ); + } + if( sgi_check_bootfile( "/unix" ) ) + { + printf( "\tYou have chosen an unusual boot file name.\n" ); + } + } + return gap; +} + +void +sgi_change_sysid( int i, int sys ) +{ + if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */ + { + printf("Sorry You may change the Tag of non-empty partitions.\n"); + return; + } + if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR)) + && (sgi_get_start_sector(i)<1) ) + { + read_chars( + "It is highly recommended that the partition at offset 0\n" + "is of type \"SGI volhdr\", the IRIX system will rely on it to\n" + "retrieve from its directory standalone tools like sash and fx.\n" + "Only the \"SGI volume\" entire disk section may violate this.\n" + "Type YES if you are sure about tagging this partition differently.\n" ); + if (strcmp (line_ptr, "YES\n")) + return; + } + sgilabel->partitions[i].id = SSWAP32(sys); + return; +} + +int +sgi_entire( void ) +{ /* returns partition index of first entry marked as entire disk */ + int i=0; + for( i=0; i<16; i++ ) + if( sgi_get_sysid(i) == SGI_VOLUME ) + return i; + return -1; +} + +int +sgi_num_partitions( void ) +{ + int i=0, + n=0; + for( i=0; i<16; i++ ) + if( sgi_get_num_sectors(i)!=0 ) + n++; + return n; +} + +static +void +sgi_set_partition( int i, uint start, uint length, int sys ) +{ + sgilabel->partitions[i].id = + SSWAP32( sys ); + sgilabel->partitions[i].num_sectors = + SSWAP32( length ); + sgilabel->partitions[i].start_sector = + SSWAP32( start ); + changed[i] = 1; + if( sgi_gaps(0) < 0 ) /* rebuild freelist */ + { + printf( "Do You know, You got a partition overlap on the disk?\n" ); + } + return; +} + +static +void +sgi_set_entire( void ) +{ + int n; + for( n=10; nsys_ind ) + { + old[i].sysid = part_table[i]->sys_ind; + old[i].start = get_start_sect( part_table[i] ); + old[i].nsect = get_nr_sects( part_table[i] ); + printf( "Trying to keep parameters of partition %d.\n", i ); + if( debug ) + printf( "ID=%02x\tSTART=%d\tLENGTH=%d\n", + old[i].sysid, old[i].start, old[i].nsect ); + } + } + } + memset(buffer, 0, SECTOR_SIZE); + sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC); + sgilabel->boot_part = SSWAP16(0); + sgilabel->swap_part = SSWAP16(1); strncpy( + sgilabel->boot_file , "/unix\0\0\0\0\0\0\0\0\0\0\0", 16 ); + sgilabel->devparam.skew = (0); + sgilabel->devparam.gap1 = (0); + sgilabel->devparam.gap2 = (0); + sgilabel->devparam.sparecyl = (0); + sgilabel->devparam.pcylcount = SSWAP16(geometry.cylinders); + sgilabel->devparam.head_vol0 = SSWAP16(0); + sgilabel->devparam.ntrks = SSWAP16(geometry.heads); + /* tracks/cylinder (heads) */ + sgilabel->devparam.cmd_tag_queue_depth = (0); + sgilabel->devparam.unused0 = (0); + sgilabel->devparam.unused1 = SSWAP16(0); + sgilabel->devparam.nsect = SSWAP16(geometry.sectors); + /* sectors/track */ + sgilabel->devparam.bytes = SSWAP16(512); + sgilabel->devparam.ilfact = SSWAP16(1); + sgilabel->devparam.flags = SSWAP32(TRACK_FWD|\ + IGNORE_ERRORS|RESEEK); + sgilabel->devparam.datarate = SSWAP32(0); + sgilabel->devparam.retries_on_error = SSWAP32(1); + sgilabel->devparam.ms_per_word = SSWAP32(0); + sgilabel->devparam.xylogics_gap1 = SSWAP16(0); + sgilabel->devparam.xylogics_syncdelay = SSWAP16(0); + sgilabel->devparam.xylogics_readdelay = SSWAP16(0); + sgilabel->devparam.xylogics_gap2 = SSWAP16(0); + sgilabel->devparam.xylogics_readgate = SSWAP16(0); + sgilabel->devparam.xylogics_writecont = SSWAP16(0); + memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 ); + memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 ); + sgi_label = 1; + partitions = 16; + volumes = 15; + sgi_set_entire(); + sgi_set_volhdr(); + for (i = 0; i < 4; i++) + { + if( old[i].sysid ) + { + sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid ); + } + } + return; +} + +void +sgi_set_ilfact( void ) +{ + /* do nothing in the beginning */ +} + +void +sgi_set_rspeed( void ) +{ + /* do nothing in the beginning */ +} + +void +sgi_set_pcylcount( void ) +{ + /* do nothing in the beginning */ +} + +void +sgi_set_xcyl( void ) +{ + /* do nothing in the beginning */ +} + +void +sgi_set_ncyl( void ) +{ + /* do nothing in the beginning */ +} + +/* _____________________________________________________________ + */ + +sgiinfo* +fill_sgiinfo( void ) +{ + sgiinfo*info=calloc( 1, sizeof(sgiinfo) ); + info->magic=SSWAP32(SGI_INFO_MAGIC); + info->b1=SSWAP32(-1); + info->b2=SSWAP16(-1); + info->b3=SSWAP16(1); + /* You may want to replace this string !!!!!!! */ + strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" ); + strcpy( info->serial, "0000" ); + info->check1816 = SSWAP16(18*256 +16 ); + strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" ); + return info; +} diff --git a/fdisk/fdisksgilabel.h b/fdisk/fdisksgilabel.h new file mode 100644 index 00000000..6eb7293f --- /dev/null +++ b/fdisk/fdisksgilabel.h @@ -0,0 +1,133 @@ +#include /* for __u32 etc */ +/* + * Copyright (C) Andreas Neuper, Sep 1998. + * This file may be modified and redistributed under + * the terms of the GNU Public License. + */ + +struct device_parameter { /* 48 bytes */ + unsigned char skew; + unsigned char gap1; + unsigned char gap2; + unsigned char sparecyl; + unsigned short pcylcount; + unsigned short head_vol0; + unsigned short ntrks; /* tracks in cyl 0 or vol 0 */ + unsigned char cmd_tag_queue_depth; + unsigned char unused0; + unsigned short unused1; + unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */ + unsigned short bytes; + unsigned short ilfact; + unsigned int flags; /* controller flags */ + unsigned int datarate; + unsigned int retries_on_error; + unsigned int ms_per_word; + unsigned short xylogics_gap1; + unsigned short xylogics_syncdelay; + unsigned short xylogics_readdelay; + unsigned short xylogics_gap2; + unsigned short xylogics_readgate; + unsigned short xylogics_writecont; +}; + +#define SGI_VOLUME 0x06 +#define SGI_EFS 0x07 +#define SGI_SWAP 0x03 +#define SGI_VOLHDR 0x00 +#define ENTIRE_DISK SGI_VOLUME +/* + * controller flags + */ +#define SECTOR_SLIP 0x01 +#define SECTOR_FWD 0x02 +#define TRACK_FWD 0x04 +#define TRACK_MULTIVOL 0x08 +#define IGNORE_ERRORS 0x10 +#define RESEEK 0x20 +#define ENABLE_CMDTAGQ 0x40 + +typedef struct { + unsigned int magic; /* expect SGI_LABEL_MAGIC */ + unsigned short boot_part; /* active boot partition */ + unsigned short swap_part; /* active swap partition */ + unsigned char boot_file[16]; /* name of the bootfile */ + struct device_parameter devparam; /* 1 * 48 bytes */ + struct volume_directory { /* 15 * 16 bytes */ + unsigned char vol_file_name[8]; /* an character array */ + unsigned int vol_file_start; /* number of logical block */ + unsigned int vol_file_size; /* number of bytes */ + } directory[15]; + struct sgi_partition { /* 16 * 12 bytes */ + unsigned int num_sectors; /* number of blocks */ + unsigned int start_sector; /* sector must be cylinder aligned */ + unsigned int id; + } partitions[16]; + unsigned int csum; + unsigned int fillbytes; +} sgi_partition; + +typedef struct { + unsigned int magic; /* looks like a magic number */ + unsigned int a2; + unsigned int a3; + unsigned int a4; + unsigned int b1; + unsigned short b2; + unsigned short b3; + unsigned int c[16]; + unsigned short d[3]; + unsigned char scsi_string[50]; + unsigned char serial[137]; + unsigned short check1816; + unsigned char installer[225]; +} sgiinfo; + +#define SGI_LABEL_MAGIC 0x0be5a941 +#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b +#define SGI_INFO_MAGIC 0x00072959 +#define SGI_INFO_MAGIC_SWAPPED 0x59290700 +#define SSWAP16(x) (other_endian ? __swap16(x) \ + : (__u16)(x)) +#define SSWAP32(x) (other_endian ? __swap32(x) \ + : (__u32)(x)) +#define scround(x) ((x+(display_factor-1)*unit_flag)/display_factor) + +/* fdisk.c */ +#define sgilabel ((sgi_partition *)buffer) +#define sgiparam (sgilabel->devparam) +extern char buffer[MAX_SECTOR_SIZE]; +extern char changed[MAXIMUM_PARTS]; +extern uint heads, sectors, cylinders; +extern int show_begin; +extern int sgi_label; +extern char *partition_type(unsigned char type); +extern void update_units(void); +extern char read_chars(char *mesg); + +/* fdisksgilabel.c */ +extern struct systypes sgi_sys_types[]; +extern void sgi_nolabel( void ); +extern int check_sgi_label( void ); +extern void sgi_list_table( int xtra ); +extern void sgi_change_sysid( int i, int sys ); +extern int sgi_get_start_sector( int i ); +extern int sgi_get_num_sectors( int i ); +extern int sgi_get_sysid( int i ); +extern void sgi_delete_partition( int i ); +extern void sgi_add_partition( int n, int sys ); +extern void create_sgilabel( void ); +extern void create_sgiinfo( void ); +extern int verify_sgi( int verbose ); +extern void sgi_write_table( void ); +extern void sgi_set_ilfact( void ); +extern void sgi_set_rspeed( void ); +extern void sgi_set_pcylcount( void ); +extern void sgi_set_xcyl( void ); +extern void sgi_set_ncyl( void ); +extern void sgi_set_bootpartition( int i ); +extern void sgi_set_swappartition( int i ); +extern int sgi_get_bootpartition( void ); +extern int sgi_get_swappartition( void ); +extern void sgi_set_bootfile( const char* aFile ); +extern const char *sgi_get_bootfile( void ); diff --git a/disk-utils/fdisksunlabel.c b/fdisk/fdisksunlabel.c similarity index 73% rename from disk-utils/fdisksunlabel.c rename to fdisk/fdisksunlabel.c index a5a87b8d..70837737 100644 --- a/disk-utils/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -6,7 +6,6 @@ * * Merged with fdisk for other architectures, aeb, June 1998. */ -#if defined (sparc) #include /* stderr */ #include /* uint */ @@ -16,16 +15,18 @@ #include /* stat */ #include -#include +#if 1 +#include /* SCSI_IOCTL_GET_IDLUN */ +#endif #include /* FLOPPY_MAJOR */ #include /* HDIO_GETGEO */ #include "fdisk.h" #include "fdisksunlabel.h" -int other_endian = 0; -int scsi_disk = 0; -int floppy = 0; +static int other_endian = 0; +static int scsi_disk = 0; +static int floppy = 0; #define LINUX_SWAP 0x82 #define LINUX_NATIVE 0x83 @@ -45,10 +46,10 @@ struct systypes sun_sys_types[] = { { 0, NULL } }; -inline unsigned short __swap16(unsigned short x) { +static inline unsigned short __swap16(unsigned short x) { return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8); } -inline __u32 __swap32(__u32 x) { +static inline __u32 __swap32(__u32 x) { return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24); } @@ -88,12 +89,20 @@ void set_sun_partition(int i, uint start, uint stop, int sysid) changed[i] = 1; } +void sun_nolabel(void) +{ + sun_label = 0; + sunlabel->magic = 0; + partitions = 4; +} + int check_sun_label(void) { unsigned short *ush; int csum; - if (sunlabel->magic != SUN_LABEL_MAGIC && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { + if (sunlabel->magic != SUN_LABEL_MAGIC && + sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { sun_label = 0; other_endian = 0; return 0; @@ -145,6 +154,74 @@ struct sun_predefined_drives { {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, }; +struct sun_predefined_drives * +sun_autoconfigure_scsi() { + struct sun_predefined_drives *p = NULL; + +#ifdef SCSI_IOCTL_GET_IDLUN + unsigned int id[2]; + char buffer[2048]; + char buffer2[2048]; + FILE *pfd; + char *vendor; + char *model; + char *q; + int i; + + if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) { + sprintf(buffer, + "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", +#if 0 + ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33, +#else + /* This is very wrong (works only if you have one HBA), + but I haven't found a way how to get hostno + from the current kernel */ + 0, +#endif + (id[0]>>16)&0xff, + id[0]&0xff, + (id[0]>>8)&0xff); + pfd = fopen("/proc/scsi/scsi","r"); + if (pfd) { + while (fgets(buffer2,2048,pfd)) { + if (!strcmp(buffer, buffer2)) { + if (fgets(buffer2,2048,pfd)) { + q = strstr(buffer2,"Vendor: "); + if (q) { + q += 8; + vendor = q; + q = strstr(q," Model: "); + if (q) { + *q = 0; + q += 8; + model = q; + q = strstr(q," Rev: "); + if (q) { + *q = 0; + for (i = 0; i < SIZE(sun_drives); i++) { + if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) + continue; + if (!strstr(model, sun_drives[i].model)) + continue; + printf("Autoconfigure found a %s%s%s\n",sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model); + p = sun_drives + i; + break; + } + } + } + } + } + break; + } + } + fclose(pfd); + } + } +#endif + return p; +} + void create_sunlabel(void) { struct hd_geometry geometry; @@ -181,64 +258,10 @@ void create_sunlabel(void) } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) { p = sun_drives + c - 'A'; break; - } else if (c == '0') + } else if (c == '0') { break; - else if (c == '?' && scsi_disk) { - unsigned int id[2]; - char buffer[2048]; - char buffer2[2048]; - FILE *pfd; - char *vendor; - char *model; - char *q; - - if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) { - sprintf(buffer, "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", -#if 0 - ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33, -#else - /* This is very wrong (works only if you have one HBA), but I haven't find a way how to get hostno from the current kernel */ - 0, -#endif - (id[0]>>16)&0xff, - id[0]&0xff, - (id[0]>>8)&0xff); - pfd = fopen("/proc/scsi/scsi","r"); - if (pfd) { - while (fgets(buffer2,2048,pfd)) { - if (!strcmp(buffer, buffer2)) { - if (fgets(buffer2,2048,pfd)) { - q = strstr(buffer2,"Vendor: "); - if (q) { - q += 8; - vendor = q; - q = strstr(q," Model: "); - if (q) { - *q = 0; - q += 8; - model = q; - q = strstr(q," Rev: "); - if (q) { - *q = 0; - for (i = 0; i < SIZE(sun_drives); i++) { - if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) - continue; - if (!strstr(model, sun_drives[i].model)) - continue; - printf("Autoconfigure found a %s%s%s\n",sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model); - p = sun_drives + i; - break; - } - } - } - } - } - break; - } - } - fclose(pfd); - } - } + } else if (c == '?' && scsi_disk) { + p = sun_autoconfigure_scsi(); if (!p) printf("Autoconfigure failed.\n"); else @@ -267,23 +290,26 @@ void create_sunlabel(void) sunlabel->ilfact = SSWAP16(1); sunlabel->sparecyl = 0; } else { - if (heads) - heads = read_int(1,heads,1024,deflt,"Heads"); - else - heads = read_int(1,1,1024,ignore,"Heads"); - if (sectors) - sectors = read_int(1,sectors,1024,deflt,"Sectors/track"); - else - sectors = read_int(1,1,1024,ignore,"Sectors/track"); + heads = read_int(1,heads,1024,0,"Heads"); + sectors = read_int(1,sectors,1024,0,"Sectors/track"); if (cylinders) - cylinders = read_int(1,cylinders-2,65535,deflt,"Cylinders"); + cylinders = read_int(1,cylinders-2,65535,0,"Cylinders"); else - cylinders = read_int(1,1,65535,ignore,"Cylinders"); - sunlabel->nacyl = SSWAP16(read_int(0,2,65535,deflt,"Alternate cylinders")); - sunlabel->pcylcount = SSWAP16(read_int(0,cylinders + SSWAP16(sunlabel->nacyl),65535,deflt,"Physical cylinders")); - sunlabel->rspeed = SSWAP16(read_int(1,5400,100000,deflt,"Rotation speed (rpm)")); - sunlabel->ilfact = SSWAP16(read_int(1,1,32,deflt,"Interleave factor")); - sunlabel->sparecyl = SSWAP16(read_int(0,0,sectors,deflt,"Extra sectors per cylinder")); + cylinders = read_int(1,0,65535,0,"Cylinders"); + sunlabel->nacyl = + SSWAP16(read_int(0,2,65535,0, + "Alternate cylinders")); + sunlabel->pcylcount = + SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl), + 65535,0,"Physical cylinders")); + sunlabel->rspeed = + SSWAP16(read_int(1,5400,100000,0, + "Rotation speed (rpm)")); + sunlabel->ilfact = + SSWAP16(read_int(1,1,32,0,"Interleave factor")); + sunlabel->sparecyl = + SSWAP16(read_int(0,0,sectors,0, + "Extra sectors per cylinder")); } } else { sunlabel->sparecyl = SSWAP16(p->sparecyl); @@ -459,18 +485,22 @@ void add_sun_partition(int n, int sys) sprintf(mesg, "First %s", str_units()); for (;;) { if (whole_disk) - first = read_int(0, 0, 0, deflt, mesg); + first = read_int(0, 0, 0, 0, mesg); else - first = read_int(scround(start), scround(start), scround(stop), - ignore, mesg); + first = read_int(scround(start), scround(stop)+1, + scround(stop), 0, mesg); if (unit_flag) first *= display_factor; else - first = (first + heads * sectors - 1) / (heads * sectors); /* Starting sector has to be properly aligned */ - if (n == 2 && first != 0) printf ("It is highly recommended that third partition covers the whole disk\n" - "and is of type `Whole disk'\n"); + /* Starting sector has to be properly aligned */ + first = (first + heads * sectors - 1) / (heads * sectors); + if (n == 2 && first != 0) + printf ("\ +It is highly recommended that the third partition covers the whole disk\n\ +and is of type `Whole disk'\n"); for (i = 0; i < partitions; i++) - if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first) + if (lens[i] && starts[i] <= first + && starts[i] + lens[i] > first) break; if (i < partitions && !whole_disk) { if (n == 2 && !first) { @@ -489,14 +519,14 @@ void add_sun_partition(int n, int sys) } sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); if (whole_disk) - last = read_int(scround(stop2), scround(stop2), scround(stop2), - deflt, mesg); + last = read_int(scround(stop2), scround(stop2), scround(stop2), + 0, mesg); else if (n == 2 && !first) last = read_int(scround(first), scround(stop2), scround(stop2), - upper, mesg); + scround(first), mesg); else last = read_int(scround(first), scround(stop), scround(stop), - lower, mesg); + scround(first), mesg); if (unit_flag) last *= display_factor; if (n == 2 && !first) { @@ -520,10 +550,13 @@ void sun_delete_partition(int i) { if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && !sunlabel->partitions[i].start_cylinder && - SSWAP32(sunlabel->partitions[i].num_sectors) == heads * sectors * cylinders) - printf("If you want to maintain SunOS/Solaris compatibility, consider leaving this\n" - "partition as Whole disk (5), starting at 0, with %d sectors\n", - SSWAP32(sunlabel->partitions[i].num_sectors)); + SSWAP32(sunlabel->partitions[i].num_sectors) + == heads * sectors * cylinders) + printf("If you want to maintain SunOS/Solaris compatibility, " + "consider leaving this\n" + "partition as Whole disk (5), starting at 0, with %u " + "sectors\n", + (uint) SSWAP32(sunlabel->partitions[i].num_sectors)); sunlabel->infos[i].id = 0; sunlabel->partitions[i].num_sectors = 0; } @@ -580,23 +613,20 @@ sun_list_table(int xtra) { disk_device, heads, sectors, cylinders, str_units(), display_factor); - printf("%*s Flag %s Start End Blocks Id System\n", - w + 1, "Device", show_begin ? " Begin " : " "); + printf("%*s Flag Start End Blocks Id System\n", + w + 1, "Device"); for (i = 0 ; i < partitions; i++) { if (sunlabel->partitions[i].num_sectors) { __u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; __u32 len = SSWAP32(sunlabel->partitions[i].num_sectors); printf( - show_begin - ? "%*s%-2d %c%c%9d%9d%9d%9d%c %2x %s\n" - : "%*s%-2d %c%c%c%9d%9d%9d%c %2x %s\n", + "%*s%-2d %c%c %9ld %9ld %9ld%c %2x %s\n", /* device */ w, disk_device, i + 1, /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ', -/* begin */ show_begin ? scround(start) : ' ', -/* start */ scround(start), -/* end */ scround(start+len), -/* odd flag on end */ len / 2, len & 1 ? '+' : ' ', +/* start */ (long) scround(start), +/* end */ (long) scround(start+len), +/* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ', /* type id */ sunlabel->infos[i].id, /* type name */ (type = partition_type(sunlabel->infos[i].id)) ? type : "Unknown"); @@ -606,9 +636,9 @@ sun_list_table(int xtra) { void sun_set_alt_cyl(void) { - sunlabel->nacyl = SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), - 65535, deflt, - "Number of alternate cylinders")); + sunlabel->nacyl = + SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0, + "Number of alternate cylinders")); } void @@ -618,30 +648,30 @@ sun_set_ncyl(int cyl) { void sun_set_xcyl(void) { - sunlabel->sparecyl = SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), - sectors, deflt, - "Extra sectors per cylinder")); + sunlabel->sparecyl = + SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0, + "Extra sectors per cylinder")); } void sun_set_ilfact(void) { - sunlabel->ilfact = SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), - 32, deflt, - "Interleave factor")); + sunlabel->ilfact = + SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0, + "Interleave factor")); } void sun_set_rspeed(void) { - sunlabel->rspeed = SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), - 100000, deflt, - "Rotation speed (rpm)")); + sunlabel->rspeed = + SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0, + "Rotation speed (rpm)")); } void sun_set_pcylcount(void) { - sunlabel->pcylcount=SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), - 65535, deflt, - "Number of physical cylinders")); + sunlabel->pcylcount = + SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0, + "Number of physical cylinders")); } void @@ -658,4 +688,3 @@ sun_write_table(void) { fatal(unable_to_write); } -#endif /* sparc */ diff --git a/disk-utils/fdisksunlabel.h b/fdisk/fdisksunlabel.h similarity index 97% rename from disk-utils/fdisksunlabel.h rename to fdisk/fdisksunlabel.h index 037e437c..d9d3706d 100644 --- a/disk-utils/fdisksunlabel.h +++ b/fdisk/fdisksunlabel.h @@ -40,7 +40,7 @@ typedef struct { /* fdisk.c */ extern char changed[MAXIMUM_PARTS]; -extern char buffer[SECTOR_SIZE]; +extern char buffer[MAX_SECTOR_SIZE]; extern uint heads, sectors, cylinders; extern int show_begin; extern int sun_label; @@ -56,6 +56,7 @@ extern struct systypes sun_sys_types[]; extern int get_num_sectors(struct sun_partition p); extern void guess_device_type(int fd); extern int check_sun_label(void); +extern void sun_nolabel(void); extern void create_sunlabel(void); extern void sun_delete_partition(int i); extern void sun_change_sysid(int i, int sys); diff --git a/disk-utils/llseek.c b/fdisk/llseek.c similarity index 100% rename from disk-utils/llseek.c rename to fdisk/llseek.c diff --git a/disk-utils/sfdisk.8 b/fdisk/sfdisk.8 similarity index 97% rename from disk-utils/sfdisk.8 rename to fdisk/sfdisk.8 index 33f10dab..e7f3e82b 100644 --- a/disk-utils/sfdisk.8 +++ b/fdisk/sfdisk.8 @@ -120,6 +120,7 @@ As a precaution, one can save the sectors changed by .nf .if t .ft CW % sfdisk /dev/hdd \-O hdd-partition-sectors.save +\&... % .if t .ft R .fi @@ -136,6 +137,14 @@ the old situation with .if t .ft R .fi .RE +.LP +(This is not the same as saving the old partition table: +a readable version of the old partition table can be saved +using the \-d option. However, if you create logical partitions, +the sectors describing them are located somewhere on disk, +possibly on sectors that were not part of the partition table +before. Thus, the information the \-O option saves is not a binary +version of the output of \-d.) There are many options. @@ -195,7 +204,7 @@ and change nothing else. (Probably this fifth partition is called /dev/hdb5, but you are free to call it something else, like `/my_equipment/disks/2/5' or so). .TP -.BI \-A " number" +.BI \-A "number" Make the indicated partition(s) active, and all others inactive. .TP .BI \-c " or " \-\-id " number [Id]" diff --git a/disk-utils/sfdisk.c b/fdisk/sfdisk.c similarity index 98% rename from disk-utils/sfdisk.c rename to fdisk/sfdisk.c index 8fbe778f..c3f470f8 100644 --- a/disk-utils/sfdisk.c +++ b/fdisk/sfdisk.c @@ -610,6 +610,7 @@ struct systypes { {0xe1, "DOS access or SpeedStor 12-bit FAT extended partition"}, {0xe3, "DOS R/O or SpeedStor"}, {0xe4, "SpeedStor 16-bit FAT extended partition < 1024 cyl."}, + {0xeb, "BeOS fs"}, {0xf1, "SpeedStor"}, {0xf2, "DOS 3.3+ secondary"}, {0xf4, "SpeedStor large partition"}, @@ -2254,7 +2255,8 @@ static struct devd { } defdevs[] = { { "hd", "abcdefgh" }, { "sd", "abcde" }, - { "xd", "ab" } + { "xd", "ab" }, + { "ed", "abcd" } }; int @@ -2315,10 +2317,10 @@ main(int argc, char **argv) { else progn++; if (!strcmp(progn, "activate")) - activate = 1; /* equivalent to `fdisk -A' */ + activate = 1; /* equivalent to `sfdisk -A' */ #if 0 /* not important enough to deserve a name */ else if (!strcmp(progn, "unhide")) - unhide = 1; /* equivalent to `fdisk -U' */ + unhide = 1; /* equivalent to `sfdisk -U' */ #endif else fdisk = 1; @@ -2439,9 +2441,9 @@ main(int argc, char **argv) { if (optind == argc) { if (activate) - activate_usage(fdisk ? "fdisk -A" : progn); + activate_usage(fdisk ? "sfdisk -A" : progn); else if (unhide) - unhide_usage(fdisk ? "fdisk -U" : progn); + unhide_usage(fdisk ? "sfdisk -U" : progn); else usage(); } @@ -2469,11 +2471,11 @@ main(int argc, char **argv) { } if (do_id) { if ((do_id & PRINT_ID) != 0 && optind != argc-2) - fatal("usage: fdisk --print-id device partition-number\n"); + fatal("usage: sfdisk --print-id device partition-number\n"); else if ((do_id & CHANGE_ID) != 0 && optind != argc-3) - fatal("usage: fdisk --change-id device partition-number Id\n"); + fatal("usage: sfdisk --change-id device partition-number Id\n"); else if (optind != argc-3 && optind != argc-2) - fatal("usage: fdisk --id device partition-number [Id]\n"); + 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); @@ -2571,6 +2573,11 @@ do_size (char *dev, int silent) { } 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: %9d\n", dev, size); else @@ -2586,15 +2593,15 @@ do_size (char *dev, int silent) { * * Call: activate /dev/hda 2 5 7 make these partitions active * and the remaining ones inactive - * Or: fdisk -A /dev/hda 2 5 7 + * Or: sfdisk -A /dev/hda 2 5 7 * * If only a single partition must be active, one may also use the form - * fdisk -A2 /dev/hda + * sfdisk -A2 /dev/hda * - * With "activate /dev/hda" or "fdisk -A /dev/hda" the active partitions + * 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 "fdisk -A /dev/hda none". - * Use something like `echo ",,,*" | fdisk -N2 /dev/hda' to only make + * "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 @@ -2825,7 +2832,7 @@ Use the --no-reread flag to suppress this check.\n"); while (c != '\n' && c != EOF) c = getchar(); if (c == EOF) - printf("\nfdisk: premature end of input\n"); + 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') { diff --git a/disk-utils/sfdisk.examples b/fdisk/sfdisk.examples similarity index 100% rename from disk-utils/sfdisk.examples rename to fdisk/sfdisk.examples diff --git a/games/Makefile b/games/Makefile index 49b9f981..58a8f8f6 100644 --- a/games/Makefile +++ b/games/Makefile @@ -20,7 +20,7 @@ all: $(USRGAMES) # Rules for everything else -banner: banner.o $(BSD)/getopt.o $(BSD)/err.o +banner: banner.o $(ERR_O) ddate: ddate.o install: all diff --git a/getopt/COPYING b/getopt-1.0.3a/COPYING similarity index 100% rename from getopt/COPYING rename to getopt-1.0.3a/COPYING diff --git a/getopt/Changelog b/getopt-1.0.3a/Changelog similarity index 53% rename from getopt/Changelog rename to getopt-1.0.3a/Changelog index 0480a1de..24a4c323 100644 --- a/getopt/Changelog +++ b/getopt-1.0.3a/Changelog @@ -1,3 +1,9 @@ +980628: Bumped up version number to 1.0.3 +980628: Removed remaining incompatibility with tcsh-6.02 from parse.tcsh +980626: Added separate Makefile for util-linux +980625: Removed several bugs from parse.tcsh, partly thanks to Volker Kuhlmann + (v.kuhlmann@elec.canterbury.ac.nz). +980612: Removed reference to getopt in util-linux 980611: Bumped up version number to 1.0.2 980611: Fixed --version bug (was not available, though documented!) 980611: Removed compiler warnings. diff --git a/getopt-1.0.3a/Makefile b/getopt-1.0.3a/Makefile new file mode 100644 index 00000000..0d4a5ad0 --- /dev/null +++ b/getopt-1.0.3a/Makefile @@ -0,0 +1,52 @@ +.SUFFIXES: + +include ../MCONFIG + +GETOPTDIR=$(USRLIBDIR)/getopt + +# Define this to 0 to use the getopt(3) routines in this package. +LIBCGETOPT=1 + +SHELL=/bin/sh + +LD=ld +RM=rm -f +INSTALL=install + +CPPFLAGS=-DLIBCGETOPT=$(LIBCGETOPT) +ifeq ($(LIBCGETOPT),0) +CPPFLAGS+=-I./gnu +endif + +# -Wcast-align causes problems with the identifier stderr on alpha's +# with an old glibc. +# -Wbad-function-cast and -Wmissing-declarations are unknown for gcc 2.5.8. +WARNINGS=-Wall \ + -W -Wshadow -Wpointer-arith -Wcast-qual \ + -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline +CFLAGS=$(WARNINGS) $(OPT) + +SOURCES=getopt.c +ifeq ($(LIBCGETOPT),0) +SOURCES+=gnu/getopt.c gnu/getopt1.c +endif + +OBJECTS=$(SOURCES:.c=.o) + +BINARIES=getopt + +.PHONY: all clean realclean +all: $(BINARIES) + +clean: + -$(RM) $(OBJECTS) $(BINARIES) + +getopt: $(OBJECTS) + $(CC) $(LDFLAGS) $< -o $@ + +install: getopt + $(INSTALLDIR) $(USRBINDIR) $(MAN1DIR) $(GETOPTDIR) + $(INSTALLBIN) getopt $(USRBINDIR) + $(INSTALLMAN) getopt.1 $(MAN1DIR) + $(INSTALLBIN) parse.bash parse.tcsh test.bash test.tcsh $(GETOPTDIR) diff --git a/getopt/README b/getopt-1.0.3a/README similarity index 93% rename from getopt/README rename to getopt-1.0.3a/README index 04addba9..1d795f5e 100644 --- a/getopt/README +++ b/getopt-1.0.3a/README @@ -3,9 +3,9 @@ This package contains a reimplementation of getopt(1). PREFACE Getopt(1) is a program to help shell scripts parse command-line parameters. -It is for example included in the util-linux distribution. But, there are -some problems with that getopt(1) implementation, as listed in the -'BUGS' section of its man-page: +It is for example included in the util-linux distribution (upto version +2.7.1). But, there are some problems with that getopt(1) implementation, +as listed in the 'BUGS' section of its man-page: >BUGS > Whatever getopt(3) has. diff --git a/getopt/TODO b/getopt-1.0.3a/TODO similarity index 83% rename from getopt/TODO rename to getopt-1.0.3a/TODO index e701f666..70f2ea9c 100644 --- a/getopt/TODO +++ b/getopt-1.0.3a/TODO @@ -2,3 +2,5 @@ Other shells, like zsh and ash, should be supported (perhaps they will work already, depending on quoting conventions). (zsh seems OK). Perhaps a nice configure script? + +Add a `test' target in Makefile. diff --git a/getopt/getopt.1 b/getopt-1.0.3a/getopt.1 similarity index 100% rename from getopt/getopt.1 rename to getopt-1.0.3a/getopt.1 diff --git a/getopt/getopt.c b/getopt-1.0.3a/getopt.c similarity index 99% rename from getopt/getopt.c rename to getopt-1.0.3a/getopt.c index 00be49f3..de643f1a 100644 --- a/getopt/getopt.c +++ b/getopt-1.0.3a/getopt.c @@ -358,7 +358,7 @@ int main(int argc, char *argv[]) { char *optstr=NULL; char *name=NULL; - char opt; + int opt; int compatible=0; init_longopt(); @@ -421,7 +421,7 @@ int main(int argc, char *argv[]) case 'T': exit(4); case 'V': - printf("getopt (enhanced) 1.0.2\n"); + printf("getopt (enhanced) 1.0.3\n"); exit(0); case '?': case ':': diff --git a/getopt/gnu/getopt.c b/getopt-1.0.3a/gnu/getopt.c similarity index 100% rename from getopt/gnu/getopt.c rename to getopt-1.0.3a/gnu/getopt.c diff --git a/getopt/gnu/getopt.h b/getopt-1.0.3a/gnu/getopt.h similarity index 100% rename from getopt/gnu/getopt.h rename to getopt-1.0.3a/gnu/getopt.h diff --git a/getopt/gnu/getopt1.c b/getopt-1.0.3a/gnu/getopt1.c similarity index 100% rename from getopt/gnu/getopt1.c rename to getopt-1.0.3a/gnu/getopt1.c diff --git a/getopt/parse.bash b/getopt-1.0.3a/parse.bash similarity index 100% rename from getopt/parse.bash rename to getopt-1.0.3a/parse.bash diff --git a/getopt/parse.tcsh b/getopt-1.0.3a/parse.tcsh similarity index 83% rename from getopt/parse.tcsh rename to getopt-1.0.3a/parse.tcsh index 7d4f4271..2266d0e6 100644 --- a/getopt/parse.tcsh +++ b/getopt-1.0.3a/parse.tcsh @@ -1,9 +1,9 @@ #!/bin/tcsh # A small example program for using the new getopt(1) program. -# This program will only work with bash(1) -# An similar program using the tcsh(1) script language can be found -# as parse.tcsh +# This program will only work with tcsh(1) +# An similar program using the bash(1) script language can be found +# as parse.bash # Example input and output (from the tcsh prompt): # ./parse.tcsh -a par1 'another arg' --c-long 'wow\!*\?' -cmore -b " very long " @@ -37,8 +37,6 @@ endif # The 'q` stops doing any silly substitutions. eval set argv=\($temp:q\) -set - while (1) switch($1:q) case -a: @@ -47,7 +45,7 @@ while (1) breaksw; case -b: case --b-long: - echo "Option b, argument "\`$2\' ; shift ; shift + echo "Option b, argument "\`$2:q\' ; shift ; shift breaksw case -c: case --c-long: @@ -58,7 +56,7 @@ while (1) if ($2:q == "") then echo "Option c, no argument" else - echo "Option c, argument "\`$2\' + echo "Option c, argument "\`$2:q\' endif shift; shift breaksw @@ -71,6 +69,9 @@ while (1) end echo "Remaining arguments:" -foreach el ($argv:q) - echo '--> '\`$el:q\' +# foreach el ($argv:q) created problems for some tcsh-versions (at least +# 6.02). So we use another shift-loop here: +while ($#argv > 0) + echo '--> '\`$1:q\' + shift end diff --git a/getopt/test.bash b/getopt-1.0.3a/test.bash similarity index 100% rename from getopt/test.bash rename to getopt-1.0.3a/test.bash diff --git a/getopt/test.tcsh b/getopt-1.0.3a/test.tcsh similarity index 100% rename from getopt/test.tcsh rename to getopt-1.0.3a/test.tcsh diff --git a/getopt/Makefile b/getopt/Makefile deleted file mode 100644 index 368291f0..00000000 --- a/getopt/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -.SUFFIXES: - -include ../MCONFIG - -prefix=$(DESTDIR)/usr -bindir=$(USRBINDIR) -mandir=$(MANDIR) -man1dir=$(MAN1DIR)/man1 -getoptdir=$(USRLIBDIR)/getopt - -# Define this to 0 to use the getopt(3) routines in this package. -LIBCGETOPT=1 - -SHELL=/bin/sh - -LD=ld -RM=rm -f -INSTALL=install - -CPPFLAGS=-DLIBCGETOPT=$(LIBCGETOPT) -ifeq ($(LIBCGETOPT),0) -CPPFLAGS+=-I./gnu -endif -WARNINGS=-Wall \ - -W -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual \ - -Wcast-align -Wmissing-declarations \ - -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ - -Wnested-externs -Winline -CFLAGS=$(WARNINGS) $(OPT) - -sources=getopt.c -ifeq ($(LIBCGETOPT),0) -sources+=gnu/getopt.c gnu/getopt1.c -endif - -objects=$(sources:.c=.o) - -binaries=getopt - -.PHONY: all clean realclean -all: $(binaries) - -clean: - -$(RM) $(objects) $(binaries) - -%.o: %.c - $(CC) -c $(CPPFLAGS) $(CFLAGS) $*.c -o $*.o - -getopt: $(objects) - $(CC) $(LDFLAGS) -o $@ $(objects) - -install: getopt - $(INSTALL) -m 755 getopt $(bindir) - $(INSTALL) -m 644 getopt.1 $(man1dir) - $(INSTALL) -m 755 -d $(getoptdir) - $(INSTALL) -m 754 parse.bash parse.tcsh test.bash test.tcsh $(getoptdir) diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 00000000..5503a605 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,17 @@ +include ../MCONFIG + +CFLAGS=-I$(LIB) $(OPT) + +all: err.o my_reboot.o setproctitle.o + +err.o: err.c + +my_reboot.o: my_reboot.c linux_reboot.h + +setproctitle.o: setproctitle.h + +.PHONY: clean +clean: + -rm -f *.o *~ core + +install: diff --git a/bsd/err.c b/lib/err.c similarity index 100% rename from bsd/err.c rename to lib/err.c diff --git a/bsd/err.h b/lib/err.h similarity index 100% rename from bsd/err.h rename to lib/err.h diff --git a/lib/linux_reboot.h b/lib/linux_reboot.h new file mode 100644 index 00000000..780d7509 --- /dev/null +++ b/lib/linux_reboot.h @@ -0,0 +1,30 @@ +extern int my_reboot(int); + +/* + * Magic values required to use _reboot() system call. + */ + +#define LINUX_REBOOT_MAGIC1 0xfee1dead +#define LINUX_REBOOT_MAGIC2 672274793 +#define LINUX_REBOOT_MAGIC2A 85072278 +#define LINUX_REBOOT_MAGIC2B 369367448 + + +/* + * Commands accepted by the _reboot() system call. + * + * RESTART Restart system using default command and mode. + * HALT Stop OS and give system control to ROM monitor, if any. + * CAD_ON Ctrl-Alt-Del sequence causes RESTART command. + * CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task. + * POWER_OFF Stop OS and remove all power from system, if possible. + * RESTART2 Restart system using given command string. + */ + +#define LINUX_REBOOT_CMD_RESTART 0x01234567 +#define LINUX_REBOOT_CMD_HALT 0xCDEF0123 +#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF +#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000 +#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC +#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 + diff --git a/lib/my_reboot.c b/lib/my_reboot.c new file mode 100644 index 00000000..12ea4c92 --- /dev/null +++ b/lib/my_reboot.c @@ -0,0 +1,40 @@ +/* Including makes sure that on a glibc system + is included, which again defines __GLIBC__ */ +#include +#include "linux_reboot.h" + +#define USE_LIBC + +#ifdef USE_LIBC + +/* libc version */ +#if defined __GLIBC__ && __GLIBC__ >= 2 +# include +# define REBOOT(cmd) reboot(cmd) +#else +extern int reboot(int, int, int); +# define REBOOT(cmd) reboot(LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,(cmd)) +#endif +int +my_reboot(int cmd) { + return REBOOT(cmd); +} + +#else /* no USE_LIBC */ + +/* direct syscall version */ +#include + +#ifdef _syscall3 +_syscall3(int, reboot, int, magic, int, magic_too, int, cmd); +#else +/* Let us hope we have a 3-argument reboot here */ +extern int reboot(int, int, int); +#endif + +int +my_reboot(int cmd) { + return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd); +} + +#endif diff --git a/bsd/pathnames.h b/lib/pathnames.h similarity index 95% rename from bsd/pathnames.h rename to lib/pathnames.h index f6e46721..ab7b97dc 100644 --- a/bsd/pathnames.h +++ b/lib/pathnames.h @@ -68,7 +68,8 @@ #define _PATH_WTMP LOGDIR "/wtmp" #define _PATH_WTMPLOCK "/etc/wtmplock" -#define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin:." +/* no more . in DEFPATH */ +#define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin" #define _PATH_DEFPATH_ROOT SBINDIR ":/bin:" USRSBINDIR ":/usr/bin" #define _PATH_HUSHLOGIN ".hushlogin" #define _PATH_LASTLOG LOGDIR "/lastlog" @@ -81,6 +82,8 @@ #define _PATH_RC "/etc/rc" #define _PATH_REBOOT SBINDIR "/reboot" #define _PATH_SINGLE "/etc/singleboot" +#define _PATH_SHUTDOWN_CONF "/etc/shutdown.conf" + #define _PATH_SECURE "/etc/securesingle" #define _PATH_USERTTY "/etc/usertty" diff --git a/lib/setproctitle.c b/lib/setproctitle.c new file mode 100644 index 00000000..bff1362d --- /dev/null +++ b/lib/setproctitle.c @@ -0,0 +1,117 @@ +/* proctitle code - we know this to work only on linux... */ + +/* +** SETPROCTITLE -- set process title for ps (from sendmail) +** +** Parameters: +** fmt -- a printf style format string. +** +** Returns: +** none. +** +** Side Effects: +** Clobbers argv of our main procedure so ps(1) will +** display the title. +*/ + +#include +#include +#include +#include +#include "setproctitle.h" + +#ifndef SPT_PADCHAR +#define SPT_PADCHAR ' ' +#endif + +#ifndef SPT_BUFSIZE +#define SPT_BUFSIZE 2048 +#endif + +extern char** environ; + +static char** argv0; +static int argv_lth; + +void +initproctitle (int argc, char **argv) { + int i; + char **envp = environ; + + /* + * Move the environment so we can reuse the memory. + * (Code borrowed from sendmail.) + * WARNING: ugly assumptions on memory layout here; + * if this ever causes problems, #undef DO_PS_FIDDLING + */ + for (i = 0; envp[i] != NULL; i++) + continue; + environ = (char **) malloc(sizeof(char *) * (i + 1)); + if (environ == NULL) + return; + for (i = 0; envp[i] != NULL; i++) + if ((environ[i] = strdup(envp[i])) == NULL) + return; + environ[i] = NULL; + + argv0 = argv; + if (i > 0) + argv_lth = envp[i-1] + strlen(envp[i-1]) - argv0[0]; + else + argv_lth = argv0[argc-1] + strlen(argv0[argc-1]) - argv0[0]; +} + +#if 0 +/* Nice code, but many places do not know about vsnprintf ... */ +void +setproctitle (const char *fmt,...) { + char *p; + int i; + char buf[SPT_BUFSIZE]; + va_list ap; + + if (!argv0) + return; + + va_start(ap, fmt); + (void) vsnprintf(buf, SPT_BUFSIZE, fmt, ap); + va_end(ap); + + i = strlen (buf); + if (i > argv_lth - 2) { + i = argv_lth - 2; + buf[i] = '\0'; + } + (void) strcpy (argv0[0], buf); + p = &argv0[0][i]; + while (i < argv_lth) + *p++ = SPT_PADCHAR, i++; + argv0[1] = NULL; +} +#else +void +setproctitle (const char *prog, const char *txt) { + char *p; + int i; + char buf[SPT_BUFSIZE]; + + if (!argv0) + return; + + if (strlen(prog) + strlen(txt) + 5 > SPT_BUFSIZE) + return; + + (void) sprintf(buf, "%s -- %s", prog, txt); + + i = strlen (buf); + if (i > argv_lth - 2) { + i = argv_lth - 2; + buf[i] = '\0'; + } + (void) strcpy (argv0[0], buf); + p = &argv0[0][i]; + while (i < argv_lth) + *p++ = SPT_PADCHAR, i++; + argv0[1] = NULL; +} +#endif diff --git a/lib/setproctitle.h b/lib/setproctitle.h new file mode 100644 index 00000000..d57abda6 --- /dev/null +++ b/lib/setproctitle.h @@ -0,0 +1,7 @@ + +void initproctitle (int argc, char **argv); +#if 0 +void setproctitle (const char *fmt, ...); +#else +void setproctitle (const char *prog, const char *txt); +#endif diff --git a/login-utils/Makefile b/login-utils/Makefile index 9f41fcd1..f4bbc5a9 100644 --- a/login-utils/Makefile +++ b/login-utils/Makefile @@ -82,54 +82,53 @@ all-misc: $(USRBIN.MISC) # Rules for everything else -agetty.o: $(BSD)/pathnames.h +agetty.o: $(LIB)/pathnames.h agetty: agetty.o chfn: chfn.o islocal.o setpwnam.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) chsh: chsh.o islocal.o setpwnam.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) -islocal.o: $(BSD)/pathnames.h -last.o: $(BSD)/pathnames.h -last: last.o $(BSD)/getopt.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) +islocal.o: $(LIB)/pathnames.h +last.o: $(LIB)/pathnames.h +last: last.o ifeq "$(HAVE_PAM)" "yes" -login: login.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) +login: login.o $(LIB)/setproctitle.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) else -login: login.o checktty.o - $(CC) -o $@ $^ $(CRYPT) +login: login.o $(LIB)/setproctitle.o checktty.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) endif -mesg: mesg.o $(BSD)/getopt.o $(BSD)/err.o +mesg: mesg.o $(ERR_O) newgrp: newgrp.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) -setpwnam.o: $(BSD)/pathnames.h -shutdown.o: $(BSD)/pathnames.h -shutdown: shutdown.o -simpleinit.o: $(BSD)/pathnames.h -simpleinit: simpleinit.o $(CRYPT) -vipw.o: $(BSD)/pathnames.h + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) +setpwnam.o: $(LIB)/pathnames.h +shutdown.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h +shutdown: shutdown.o $(LIB)/my_reboot.o +simpleinit.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h +simpleinit: simpleinit.o $(LIB)/my_reboot.o +vipw.o: $(LIB)/pathnames.h vipw: vipw.o -newgrp.o: $(BSD)/pathnames.h +newgrp.o: $(LIB)/pathnames.h $(CC) -c $(CFLAGS) $(PAMFL) newgrp.c wall: wall.o ttymsg.o ifeq "$(USE_TTY_GROUP)" "yes" -login.o: login.c $(BSD)/pathnames.h +login.o: login.c $(LIB)/pathnames.h $(LIB)/setproctitle.c $(LIB)/setproctitle.h $(CC) -c $(CFLAGS) $(PAMFL) -DUSE_TTY_GROUP login.c -mesg.o: mesg.c $(BSD)/err.h +mesg.o: mesg.c $(LIB)/err.h $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c else -login.o: $(BSD)/pathnames.h +login.o: $(LIB)/pathnames.h $(CC) -c $(CFLAGS) $(PAMFL) login.c -mesg.o: $(BSD)/err.h +mesg.o: $(LIB)/err.h endif -passwd: passwd.o islocal.o setpwnam.o $(CRYPT) -passwd.o: passwd.c - $(CC) -c $(CFLAGS) passwd.c +passwd: passwd.o islocal.o setpwnam.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) ifeq "$(REQUIRE_PASSWORD)" "yes" CHSH_FLAGS:=$(CHSH_FLAGS) -DREQUIRE_PASSWORD diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 03958959..96d7b38d 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -545,6 +545,9 @@ update_utmp(line) endutent(); { +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) + updwtmp(_PATH_WTMP, &ut); +#else int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { @@ -556,8 +559,9 @@ update_utmp(line) flock(lf, LOCK_UN); close(lf); } +#endif } -#else +#else /* not __linux__ */ if ((ut_fd = open(UTMP_FILE, 2)) < 0) { error("%s: open for update: %m", UTMP_FILE); } else { @@ -769,7 +773,7 @@ do_prompt(op, tp) #ifdef ISSUE FILE *fd; int oflag; - char c; + int c; struct utsname uts; (void) uname(&uts); diff --git a/login-utils/checktty.c b/login-utils/checktty.c index f01d0ee8..15873aa4 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -135,6 +135,8 @@ add_to_class(struct ttyclass *tc, char *tty) /* return true if tty is a pty. Very linux dependent */ +/* Note that the new dynamic ptys (say /dev/pty/0 etc) have major in 128-135 */ +/* We might try TIOCGPTN or so to recognise these new ones, if desired */ static int isapty(const char *tty) { @@ -146,20 +148,18 @@ isapty(const char *tty) return 0; sprintf(devname, "/dev/%s", tty); -#if defined(__linux__) && defined(PTY_SLAVE_MAJOR) - /* this is for linux 1.3 and newer */ - if((stat(devname, &stb) >= 0) - && major(stb.st_rdev) == PTY_SLAVE_MAJOR) { - return 1; - } +#if defined(__linux__) + if((stat(devname, &stb) >= 0) && S_ISCHR(stb.st_mode)) { + +#if defined(PTY_SLAVE_MAJOR) + /* this is for linux 1.3 and newer */ + if(major(stb.st_rdev) == PTY_SLAVE_MAJOR) + return 1; #endif -#if defined(__linux__) - /* this is for linux versions before 1.3, backward compat. */ - if((stat(devname, &stb) >= 0) - && major(stb.st_rdev) == TTY_MAJOR - && minor(stb.st_rdev) >= 192) { - return 1; + /* this is for linux versions before 1.3, backward compat. */ + if(major(stb.st_rdev) == TTY_MAJOR && minor(stb.st_rdev) >= 192) + return 1; } #endif return 0; diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 8e962db0..3da2360f 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -14,9 +14,6 @@ * patches from Zefram * * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - * to allow peaceful coexistence with yp: using the changes by - * Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, from - * passwd.c (now moved to setpwnam.c); * to remove trailing empty fields. Oct 5, 96. * */ @@ -32,6 +29,7 @@ #include #include #include +#include #include "my_crypt.h" #include "../version.h" @@ -81,6 +79,9 @@ extern int setpwnam P((struct passwd *pwd)); #define memzero(ptr, size) memset((char *) ptr, 0, size) +/* we do not accept gecos field sizes lengther than MAX_FIELD_SIZE */ +#define MAX_FIELD_SIZE 256 + int main (argc, argv) int argc; char *argv[]; @@ -103,6 +104,9 @@ int main (argc, argv) for (cp = whoami; *cp; cp++) if (*cp == '/') whoami = cp + 1; + /* iscntrl() below should not reject actual names */ + setlocale(LC_ALL,""); + /* * "oldf" contains the users original finger information. * "newf" contains the changed finger information, and contains NULL @@ -393,6 +397,13 @@ static int check_gecos_string (msg, gecos) { int i, c; + if (strlen(gecos) > MAX_FIELD_SIZE) { + if (msg != NULL) + printf("%s: ", msg); + printf("field is too long.\n"); + return -1; + } + for (i = 0; i < strlen (gecos); i++) { c = gecos[i]; if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { diff --git a/login-utils/chsh.1 b/login-utils/chsh.1 index 57ded290..42e87ca6 100644 --- a/login-utils/chsh.1 +++ b/login-utils/chsh.1 @@ -10,7 +10,7 @@ .\" $Revision: 1.1 $ .\" $Date: 1995/03/12 01:28:58 $ .\" -.TH CHSH 1 "October 13 1994" "chsh" "Linux Reference Manual" +.TH CHSH 1 "7 October 1998" "chsh" "Linux Reference Manual" .SH NAME chsh \- change your login shell .SH SYNOPSIS @@ -28,6 +28,8 @@ will accept the full pathname of any executable file on the system. However, it will issue a warning if the shell is not listed in the .I /etc/shells file. +On the other hand, it can also be configured such that it will +only accept shells listed in this file, unless you are root. .SH OPTIONS .TP .I "\-s, \-\-shell" diff --git a/login-utils/chsh.c b/login-utils/chsh.c index f64cd0b7..8e8a51bc 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -17,11 +17,6 @@ * suggestion from Zefram. Disallowing users with shells not in /etc/shells * from changing their shell. * - * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - * to allow peaceful coexistence with yp: using the changes by - * Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, from - * passwd.c (now moved to setpwnam.c). Oct 5, 96. - * */ #if 0 diff --git a/login-utils/last.1.orig b/login-utils/last.1.orig deleted file mode 100644 index 4d0deb88..00000000 --- a/login-utils/last.1.orig +++ /dev/null @@ -1,49 +0,0 @@ -.TH LAST 1 "20 March 1992" -.SH NAME -last \(em indicate last logins by user or terminal -.SH SYNOPSIS -.ad l -.B last -.RB [ \-\fP\fInumber\fP ] -.RB [ \-f -.IR filename ] -.RB [ \-t -.IR tty ] -.RB [ \-h -.IR hostname ] -.RI [ name ...] -.ad b -.SH DESCRIPTION -\fBLast\fP looks back in the \fBwtmp\fP file which records all logins -and logouts for information about a user, a teletype or any group of -users and teletypes. Arguments specify names of users or teletypes of -interest. If multiple arguments are given, the information which -applies to any of the arguments is printed. For example ``\fBlast root -console\fP'' would list all of root's sessions as well as all sessions -on the console terminal. \fBLast\fP displays the sessions of the -specified users and teletypes, most recent first, indicating the times -at which the session began, the duration of the session, and the -teletype which the session took place on. If the session is still -continuing or was cut short by a reboot, \fBlast\fP so indicates. -.LP -The pseudo-user \fBreboot\fP logs in at reboots of the system. -.LP -\fBLast\fP with no arguments displays a record of all logins and -logouts, in reverse order. -.LP -If \fBlast\fP is interrupted, it indicates how far the search has -progressed in \fBwtmp\fP. If interrupted with a quit signal \fBlast\fP -indicates how far the search has progressed so far, and the search -continues. -.SH OPTIONS -.IP \fB\-\fP\fInumber\fP -limit the number of entries displayed to that specified by \fInumber\fP. -.IP "\fB\-\fP \fIfilename\fP" -Use \fIfilename\fP as the name of the accounting file instead of -.BR /etc/wtmp . -.IP "\fB\-t\fP \fItty\fP" -List only logins on \fItty\fP. -.IP "\fB\-h\fP \fIhostname\fP" -List only logins from \fhostname\fP. -.SH FILES -/etc/wtmp \(em login data base diff --git a/login-utils/last.c b/login-utils/last.c index 98ffef38..cf59b8ea 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -45,6 +45,16 @@ static struct utmp buf[1024]; /* utmp read buffer */ #define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */ #define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */ +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* maximum sizes used for printing */ +/* probably we want a two-pass version that computes the right length */ +int hmax = MIN(HMAX, 16); +int lmax = MIN(LMAX, 8); +int nmax = MIN(NMAX, 16); + typedef struct arg { char *name; /* argument */ #define HOST_TYPE -2 @@ -142,19 +152,19 @@ print_partial_line(bp) char *ct; ct = ctime(&bp->ut_time); - printf("%-*.*s %-*.*s ", NMAX, NMAX, bp->ut_name, - LMAX, LMAX, bp->ut_line); + printf("%-*.*s %-*.*s ", nmax, nmax, bp->ut_name, + lmax, lmax, bp->ut_line); if (dolong) { if (bp->ut_addr) { struct in_addr foo; foo.s_addr = bp->ut_addr; - printf("%-*.*s ", HMAX, HMAX, inet_ntoa(foo)); + printf("%-*.*s ", hmax, hmax, inet_ntoa(foo)); } else { - printf("%-*.*s ", HMAX, HMAX, ""); + printf("%-*.*s ", hmax, hmax, ""); } } else { - printf("%-*.*s ", HMAX, HMAX, bp->ut_host); + printf("%-*.*s ", hmax, hmax, bp->ut_host); } if (doyear) { @@ -178,7 +188,7 @@ wtmp() lseek(), time(); int bytes, wfd; void onintr(); - char *ct, *crmsg; + char *ct, *crmsg = NULL; if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) { perror(file); @@ -191,7 +201,7 @@ wtmp() (void)signal(SIGQUIT, onintr); while (--bl >= 0) { - if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 || + if (lseek(wfd, (long)(bl * sizeof(buf)), SEEK_SET) == -1 || (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) { fprintf(stderr, "last: %s: ", file); perror((char *)NULL); @@ -206,7 +216,7 @@ wtmp() /* * utmp(5) also mentions that the user * name should be 'shutdown' or 'reboot'. - * Not checking the name causes i.e. runlevel + * Not checking the name causes e.g. runlevel * changes to be displayed as 'crash'. -thaele */ if (!strncmp(bp->ut_user, "reboot", NMAX) || diff --git a/login-utils/last.c.orig b/login-utils/last.c.orig deleted file mode 100644 index 788aa66a..00000000 --- a/login-utils/last.c.orig +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -char copyright[] = -"@(#) Copyright (c) 1987 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)last.c 5.11 (Berkeley) 6/29/88"; -#endif /* not lint */ - -/* - * last - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pathnames.h" - -#define SECDAY (24*60*60) /* seconds in a day */ -#define NO 0 /* false/no */ -#define YES 1 /* true/yes */ - -static struct utmp buf[1024]; /* utmp read buffer */ - -#define HMAX (int)sizeof(buf[0].ut_host) /* size of utmp host field */ -#define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */ -#define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */ - -typedef struct arg { - char *name; /* argument */ -#define HOST_TYPE -2 -#define TTY_TYPE -3 -#define USER_TYPE -4 - int type; /* type of arg */ - struct arg *next; /* linked list pointer */ -} ARG; -ARG *arglist; /* head of linked list */ - -typedef struct ttytab { - long logout; /* log out time */ - char tty[LMAX + 1]; /* terminal name */ - struct ttytab *next; /* linked list pointer */ -} TTY; -TTY *ttylist; /* head of linked list */ - -static long currentout, /* current logout value */ - maxrec; /* records to display */ -static char *file = _PATH_WTMP; /* wtmp file */ - -static void wtmp(), addarg(), hostconv(); -static int want(); -TTY *addtty(); -static char *ttyconv(); - -int -main(argc, argv) - int argc; - char **argv; -{ - extern int optind; - extern char *optarg; - int ch; - - while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF) - switch((char)ch) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - /* - * kludge: last was originally designed to take - * a number after a dash. - */ - if (!maxrec) - maxrec = atol(argv[optind - 1] + 1); - break; - case 'f': - file = optarg; - break; - case 'h': - hostconv(optarg); - addarg(HOST_TYPE, optarg); - break; - case 't': - addarg(TTY_TYPE, ttyconv(optarg)); - break; - case '?': - default: - fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr); - exit(1); - } - for (argv += optind; *argv; ++argv) { -#define COMPATIBILITY -#ifdef COMPATIBILITY - /* code to allow "last p5" to work */ - addarg(TTY_TYPE, ttyconv(*argv)); -#endif - addarg(USER_TYPE, *argv); - } - wtmp(); - exit(0); -} - -/* - * wtmp -- - * read through the wtmp file - */ -static void -wtmp() -{ - register struct utmp *bp; /* current structure */ - register TTY *T; /* tty list entry */ - struct stat stb; /* stat of file for size */ - long bl, delta, /* time difference */ - lseek(), time(); - int bytes, wfd; - void onintr(); - char *ct, *crmsg; - - if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) { - perror(file); - exit(1); - } - bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf); - - (void)time(&buf[0].ut_time); - (void)signal(SIGINT, onintr); - (void)signal(SIGQUIT, onintr); - - while (--bl >= 0) { - if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 || - (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) { - fprintf(stderr, "last: %s: ", file); - perror((char *)NULL); - exit(1); - } - for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) { - /* - * if the terminal line is '~', the machine stopped. - * see utmp(5) for more info. - */ - if (!strncmp(bp->ut_line, "~", LMAX)) { - /* everybody just logged out */ - for (T = ttylist; T; T = T->next) - T->logout = -bp->ut_time; - currentout = -bp->ut_time; - crmsg = strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down "; - if (!bp->ut_name[0]) - (void)strcpy(bp->ut_name, "reboot"); - if (want(bp, NO)) { - ct = ctime(&bp->ut_time); - if(bp->ut_type != LOGIN_PROCESS) - printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11); - if (maxrec && !--maxrec) - return; - } - continue; - } - /* find associated tty */ - for (T = ttylist;; T = T->next) { - if (!T) { - /* add new one */ - T = addtty(bp->ut_line); - break; - } - if (!strncmp(T->tty, bp->ut_line, LMAX)) - break; - } - if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS - && want(bp, YES)) { - ct = ctime(&bp->ut_time); - printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11); - if (!T->logout) - puts(" still logged in"); - else { - if (T->logout < 0) { - T->logout = -T->logout; - printf("- %s", crmsg); - } - else - printf("- %5.5s", ctime(&T->logout)+11); - delta = T->logout - bp->ut_time; - if (delta < SECDAY) - printf(" (%5.5s)\n", asctime(gmtime(&delta))+11); - else - printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11); - } - if (maxrec != -1 && !--maxrec) - return; - } - T->logout = bp->ut_time; - } - } - ct = ctime(&buf[0].ut_time); - printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); -} - -/* - * want -- - * see if want this entry - */ -static int -want(bp, check) - register struct utmp *bp; - int check; -{ - register ARG *step; - - if (check) - /* - * when uucp and ftp log in over a network, the entry in - * the utmp file is the name plus their process id. See - * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information. - */ - if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1)) - bp->ut_line[3] = '\0'; - else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1)) - bp->ut_line[4] = '\0'; - if (!arglist) - return(YES); - - for (step = arglist; step; step = step->next) - switch(step->type) { - case HOST_TYPE: - if (!strncmp(step->name, bp->ut_host, HMAX)) - return(YES); - break; - case TTY_TYPE: - if (!strncmp(step->name, bp->ut_line, LMAX)) - return(YES); - break; - case USER_TYPE: - if (!strncmp(step->name, bp->ut_name, NMAX)) - return(YES); - break; - } - return(NO); -} - -/* - * addarg -- - * add an entry to a linked list of arguments - */ -static void -addarg(type, arg) - int type; - char *arg; -{ - register ARG *cur; - - if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) { - fputs("last: malloc failure.\n", stderr); - exit(1); - } - cur->next = arglist; - cur->type = type; - cur->name = arg; - arglist = cur; -} - -/* - * addtty -- - * add an entry to a linked list of ttys - */ -TTY * -addtty(ttyname) - char *ttyname; -{ - register TTY *cur; - - if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) { - fputs("last: malloc failure.\n", stderr); - exit(1); - } - cur->next = ttylist; - cur->logout = currentout; - memcpy(cur->tty, ttyname, LMAX); - return(ttylist = cur); -} - -/* - * hostconv -- - * convert the hostname to search pattern; if the supplied host name - * has a domain attached that is the same as the current domain, rip - * off the domain suffix since that's what login(1) does. - */ -static void -hostconv(arg) - char *arg; -{ - static int first = 1; - static char *hostdot, - name[MAXHOSTNAMELEN]; - char *argdot; - - if (!(argdot = strchr(arg, '.'))) - return; - if (first) { - first = 0; - if (gethostname(name, sizeof(name))) { - perror("last: gethostname"); - exit(1); - } - hostdot = strchr(name, '.'); - } - if (hostdot && !strcmp(hostdot, argdot)) - *argdot = '\0'; -} - -/* - * ttyconv -- - * convert tty to correct name. - */ -static char * -ttyconv(arg) - char *arg; -{ - char *mval; - - /* - * kludge -- we assume that all tty's end with - * a two character suffix. - */ - if (strlen(arg) == 2) { - /* either 6 for "ttyxx" or 8 for "console" */ - if (!(mval = malloc((unsigned int)8))) { - fputs("last: malloc failure.\n", stderr); - exit(1); - } - if (!strcmp(arg, "co")) - (void)strcpy(mval, "console"); - else { - (void)strcpy(mval, "tty"); - (void)strcpy(mval + 3, arg); - } - return(mval); - } - if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1)) - return(arg + 5); - return(arg); -} - -/* - * onintr -- - * on interrupt, we inform the user how far we've gotten - */ -void -onintr(signo) - int signo; -{ - char *ct; - - ct = ctime(&buf[0].ut_time); - printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); - if (signo == SIGINT) - exit(1); - (void)fflush(stdout); /* fix required for rsh */ -} diff --git a/login-utils/login.1 b/login-utils/login.1 index 92a082c6..a2acbd9f 100644 --- a/login-utils/login.1 +++ b/login-utils/login.1 @@ -243,8 +243,7 @@ the user to for example run the command: xterm -e /bin/login. .PP .IP o A domain name suffix such as @.some.dom, meaning that the user may -rlogin/telnet from any host whose domain name has the suffix -.some.dom. +rlogin/telnet from any host whose domain name has the suffix .some.dom. .PP .IP o A range of IPv4 addresses, written @x.x.x.x/y.y.y.y where x.x.x.x is @@ -303,9 +302,6 @@ are allowed to log in from anywhere as is standard behavior. .BR shutdown (8) .SH BUGS -Linux, unlike other draconian operating systems, does not check -quotas. - The undocumented BSD .B \-r option is not supported. This may be required by some diff --git a/login-utils/login.c b/login-utils/login.c index ebb0a22d..c742af75 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -148,6 +148,14 @@ #define SLEEP_EXIT_TIMEOUT 5 +#ifdef __linux__ +#define DO_PS_FIDDLING +#endif + +#ifdef DO_PS_FIDDLING +#include "setproctitle.h" +#endif + #if 0 /* from before we had a lastlog.h file in linux */ struct lastlog @@ -260,9 +268,7 @@ consoletty(int fd) int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { extern int errno, optind; extern char *optarg, **environ; @@ -270,8 +276,8 @@ main(argc, argv) register int ch; register char *p; int ask, fflag, hflag, pflag, cnt; - int quietlog, passwd_req, ioctlval; - char *domain, *salt, *ttyn, *pp; + int quietlog, passwd_req; + char *domain, *ttyn; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char *ctime(), *ttyname(), *stypeof(); time_t time(); @@ -286,7 +292,12 @@ main(argc, argv) pam_handle_t *pamh = NULL; struct pam_conv conv = { misc_conv, NULL }; pid_t childPid; - int childStatus; + void (*oldSigHandler) (); +#else + char *salt, *pp; +#endif +#ifndef __linux__ + int ioctlval; #endif signal(SIGALRM, timedout); @@ -298,6 +309,9 @@ main(argc, argv) #ifdef HAVE_QUOTA quota(Q_SETUID, 0, 0, 0); #endif +#ifdef DO_PS_FIDDLING + initproctitle(argc, argv); +#endif /* * -p is used by getty to tell login not to destroy the environment @@ -313,6 +327,7 @@ main(argc, argv) username = tty = hostname = NULL; fflag = hflag = pflag = 0; passwd_req = 1; + while ((ch = getopt(argc, argv, "fh:p")) != EOF) switch (ch) { case 'f': @@ -353,8 +368,13 @@ main(argc, argv) argc -= optind; argv += optind; if (*argv) { - username = *argv; + char *p = *argv; + username = strdup(p); ask = 0; + /* wipe name - some people mistype their password here */ + /* (of course we are too late, but perhaps this helps a little ..) */ + while(*p) + *p++ = ' '; } else ask = 1; @@ -377,7 +397,7 @@ main(argc, argv) */ ioctlval = 0; ioctl(0, FIOSNBIO, &ioctlval); -#endif +#endif /* ! __linux__ */ for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); @@ -472,7 +492,7 @@ main(argc, argv) (retcode == PAM_AUTHINFO_UNAVAIL))) { pam_get_item(pamh, PAM_USER, (const void **) &username); syslog(LOG_NOTICE,"FAILED LOGIN %d FROM %s FOR %s, %s", - failcount, hostname,username,pam_strerror(pamh, retcode)); + failcount, hostname, username, pam_strerror(pamh, retcode)); fprintf(stderr,"Login incorrect\n\n"); pam_set_item(pamh,PAM_USER,NULL); retcode = pam_authenticate(pamh, 0); @@ -520,8 +540,8 @@ main(argc, argv) #else /* ! USE_PAM */ for (cnt = 0;; ask = 1) { - ioctlval = 0; # ifndef __linux__ + ioctlval = 0; ioctl(0, TIOCSETD, &ioctlval); # endif @@ -770,7 +790,7 @@ main(argc, argv) utmp.ut_line[sizeof(utmp.ut_line)-1] = 0; login(&utmp); } -#else +#else /* __linux__ defined */ /* for linux, write entries in utmp and wtmp */ { struct utmp ut; @@ -781,8 +801,19 @@ main(argc, argv) utmpname(_PATH_UTMP); setutent(); - while ((utp = getutent()) - && !(utp->ut_pid == mypid)) /* nothing */; + + /* Find mypid in utmp. +login sometimes overwrites the runlevel entry in /var/run/utmp, +confusing sysvinit. I added a test for the entry type, and the problem +was gone. (In a runlevel entry, st_pid is not really a pid but some number +calculated from the previous and current runlevel). +Michael Riepe + */ + while ((utp = getutent())) + if (utp->ut_pid == mypid + && utp->ut_type >= INIT_PROCESS + && utp->ut_type <= DEAD_PROCESS) + break; if (utp) { memcpy(&ut, utp, sizeof(ut)); @@ -813,7 +844,20 @@ main(argc, argv) pututline(&ut); endutent(); - + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) + updwtmp(_PATH_WTMP, &ut); +#else +#if 0 + /* The O_APPEND open() flag should be enough to guarantee + atomic writes at end of file. */ + if((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) { + write(wtmp, (char *)&ut, sizeof(ut)); + close(wtmp); + } +#else + /* Probably all this locking below is just nonsense, + and the short version is OK as well. */ { int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { @@ -826,8 +870,10 @@ main(argc, argv) close(lf); } } - } #endif +#endif /* __GLIBC__ */ + } +#endif /* __linux__ */ dolastlog(quietlog); @@ -903,7 +949,8 @@ main(argc, argv) setenv("TERM", termenv, 1); /* mailx will give a funny error msg if you forget this one */ - { char tmp[MAXPATHLEN]; + { + char tmp[MAXPATHLEN]; /* avoid snprintf */ if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < MAXPATHLEN) { sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name); @@ -932,6 +979,10 @@ main(argc, argv) } } #endif + +#ifdef DO_PS_FIDDLING + setproctitle("login", username); +#endif if (tty[sizeof("tty")-1] == 'S') syslog(LOG_INFO, "DIALUP AT %s BY %s", tty, pwd->pw_name); @@ -956,41 +1007,53 @@ main(argc, argv) if (!quietlog) { struct stat st; + char *mail; motd(); - /* avoid snprintf */ - if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < sizeof(tbuf)) { - sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); - if (stat(tbuf, &st) == 0 && st.st_size != 0) - printf("You have %smail.\n", - (st.st_mtime > st.st_atime) ? "new " : ""); + mail = getenv("MAIL"); + if (mail && stat(mail, &st) == 0 && st.st_size != 0) { + printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); } } signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); - signal(SIGINT, SIG_DFL); signal(SIGTSTP, SIG_IGN); signal(SIGHUP, SIG_DFL); + +#ifdef USE_PAM + /* We must fork before setuid() because we need to call + * pam_close_session() as root. + */ + signal(SIGINT, SIG_IGN); + childPid = fork(); + if (childPid < 0) { + /* error in fork() */ + fprintf(stderr,"login: failure forking: %s", strerror(errno)); + PAM_END; + exit(0); + } else if (childPid) { + /* parent - wait for child to finish, then cleanup session */ + wait(NULL); + PAM_END; + exit(0); + } + /* child */ +#endif + signal(SIGINT, SIG_DFL); /* discard permissions last so can't get killed and drop core */ if(setuid(pwd->pw_uid) < 0 && pwd->pw_uid) { syslog(LOG_ALERT, "setuid() failed"); -#ifdef USE_PAM - PAM_END; -#endif exit(1); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { printf("No directory %s!\n", pwd->pw_dir); - if (chdir("/")) { -#ifdef USE_PAM - PAM_END; -#endif + if (chdir("/")) exit(0); - } pwd->pw_dir = "/"; printf("Logging in with home = \"/\".\n"); } @@ -1023,15 +1086,6 @@ main(argc, argv) childArgv[childArgc++] = NULL; -#ifdef USE_PAM - /* There was some junk with fork()/exec()/signal()/wait() here - that was incorrect, and util-linux-2.7-11.src.rpm contains - a patch that makes the fork entirely useless. - If you introduce one again, please document in the source - what its purpose is. - aeb */ - PAM_END; -#endif /* USE_PAM */ - execvp(childArgv[0], childArgv + 1); if (!strcmp(childArgv[0], "/bin/sh")) @@ -1070,7 +1124,7 @@ getloginname() exit(0); } } - if (p > nbuf) + if (p > nbuf) { if (nbuf[0] == '-') fprintf(stderr, "login names may not start with '-'.\n"); @@ -1079,6 +1133,7 @@ getloginname() username = nbuf; break; } + } cnt2++; if (cnt2 > 50) { @@ -1190,7 +1245,7 @@ dolastlog(quiet) int fd; if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { - lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); if (!quiet) { if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) { @@ -1204,7 +1259,7 @@ dolastlog(quiet) printf("on %.*s\n", (int)sizeof(ll.ll_line), ll.ll_line); } - lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); } memset((char *)&ll, 0, sizeof(ll)); time(&ll.ll_time); diff --git a/login-utils/passwd.1 b/login-utils/passwd.1 index db44aa8e..b6a25a3f 100644 --- a/login-utils/passwd.1 +++ b/login-utils/passwd.1 @@ -34,10 +34,8 @@ reasons to choose a non-conformant password. The two argument form gives the .IR user " the " password -stated as the second argument. This may be useful when giving many -users an initial generated password. But it can also be extremely -dangerous. A simple script bug might change to root password to -something unknown. +stated as the second argument. Note that this password will +be visible to people doing `ps' or so. Avoid this form. Giving an empty string as the second argument erases the password for the user, but only in combination with the @@ -111,6 +109,3 @@ Peter Orbaek (poe@daimi.aau.dk). .br Martin Schulze (joey@infodrom.north.de) with extensive rewriting and improving done. -.br -.SH MAINTAINER -Nicolai Langfeldt (janl@math.uio.no) diff --git a/login-utils/passwd.c b/login-utils/passwd.c index 4ed1b74d..0057a283 100644 --- a/login-utils/passwd.c +++ b/login-utils/passwd.c @@ -3,17 +3,12 @@ * * Initially written for Linux by Peter Orbaek * Currently maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/ - - Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, - to allow peaceful coexistence with yp. Nov 94. - - Hacked to allow root to set passwd from command line. - by Arpad Magossanyi (mag@tas.vein.hu) - - Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - moved Alvaro's changes to setpwnam.c (so they get used - by chsh and chfn as well). Oct 5, 96. - + * + * Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, + * to allow peaceful coexistence with yp. Nov 94. + * + * Hacked to allow root to set passwd from command line. + * by Arpad Magossanyi (mag@tas.vein.hu) */ /* @@ -26,7 +21,7 @@ or running a background job that just collects all command lines) * work and second I wanted simplicity checks to be done for - * root, too. Only root can turn this of using the -f + * root, too. Only root can turn this off using the -f * switch. Okay, I started with this to support -V version * information, but one thing comes to the next. *sigh* * In a later step perhaps we'll be able to support shadow diff --git a/login-utils/shutdown.8 b/login-utils/shutdown.8 index 443acc2a..961579bd 100644 --- a/login-utils/shutdown.8 +++ b/login-utils/shutdown.8 @@ -1,6 +1,8 @@ .\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu) .\" May be distributed under the GNU General Public License -.TH SHUTDOWN 8 "20 November 1993" "Linux 1.2" "Linux Programmer's Manual" +.\" +.\" +.TH SHUTDOWN 8 "24 July 1998" "Linux 2.0" "Linux Programmer's Manual" .SH NAME shutdown \- close down the system .SH SYNOPSIS @@ -98,7 +100,29 @@ detects (and deletes). .I /etc/singleboot .I /etc/nologin .I /var/log/wtmp +.I /etc/shutdown.conf .fi +.SH CONFIG +The configuration file \fI/etc/shutdown.conf\fP is used to determine +the action to take when halting the machine. The currently supported +file format is extremely primitive. The first line must contain two +strings separated by whitespace. The first string must be +\fBHALT_ACTION\fP and the second specifies the action you wish to take +on halt. The options allowed are: +.TP +.B halt +This will simply halt the system. This is the default behaviour. +Note also that this is the fallback if another option fails. +.TP +.B power_off +This will use the kernel power shutdown facility. This is usually only +available on machines with Advanced Power Management (APM). +.TP +.I programname +This specifies a command to run to shut down the power. The first +character must be a "/". Bear in mind that this command will be run +with only the root filesystem mounted (and it will be read-only), and +no daemons running. .SH "SEE ALSO" .BR umount (8), .BR login (1), @@ -112,6 +136,6 @@ users are notified of shutdown only once or twice, instead of many times, and at shorter and shorter intervals as "apocalypse approaches." Some would construe this as a feature. .SH AUTHOR -Peter Orbaek (poe@daimi.aau.dk) -.br -Modified by jrs@world.std.com +This page documents the version of +.B shutdown +originally written by Peter Orbaek (poe@daimi.aau.dk). diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c index a63cbd6e..8ba13b64 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -1,6 +1,6 @@ /* shutdown.c - shutdown a Linux system * Initially written by poe@daimi.aau.dk - * Currently maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/ + * Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/ */ /* @@ -24,6 +24,9 @@ * Various changes and additions to resemble SunOS 4 shutdown/reboot/halt(8) * more closely by Scott Telford (s.telford@ed.ac.uk) 93/05/18. * (I butchered Scotts patches somewhat. - poe) + * + * Changes by Richard Gooch (butchered by aeb) + * introducing shutdown.conf. */ #include @@ -35,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -42,11 +46,12 @@ #include #include #include +#include "linux_reboot.h" #include "pathnames.h" -void usage(), int_handler(), write_user(struct utmp *); -void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); -void swap_off(); +static void usage(), int_handler(), write_user(struct utmp *); +static void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); +static void swap_off(), do_halt(char *); char *prog; /* name of the program */ int opt_reboot; /* true if -r option or reboot command */ @@ -57,10 +62,15 @@ char message[90]; /* reason for shutdown if any... */ int opt_single = 0; /* true is we want to boot singleuser */ char *whom; /* who is shutting the system down */ int opt_msgset = 0; /* message set on command line */ + /* change 1 to 0 if no file is to be used by default */ +int opt_use_config_file = 1; /* read _PATH_SHUTDOWN_CONF */ +char halt_action[256]; /* to find out what to do upon halt */ /* #define DEBUGGING */ #define WR(s) write(fd, s, strlen(s)) +#define ERRSTRING sys_errlist[errno] + void usage() @@ -70,19 +80,31 @@ usage() exit(1); } +void +my_puts(char *s) +{ + /* Use a fresh stdout after forking */ + freopen(_PATH_CONSOLE, "w", stdout); + puts(s); + fflush(stdout); +} + void int_handler() { unlink(_PATH_NOLOGIN); signal(SIGINT, SIG_DFL); - puts("Shutdown process aborted\n"); + my_puts("Shutdown process aborted"); exit(1); } int -main(argc, argv) - int argc; - char *argv[]; +iswhitespace(int a) { + return (a == ' ' || a == '\t'); +} + +int +main(int argc, char *argv[]) { int c,i; int fd; @@ -90,7 +112,8 @@ main(argc, argv) #ifndef DEBUGGING if(geteuid()) { - fprintf(stderr, "%s: Only root can shut a system down.\n", argv[0]); + fprintf(stderr, "%s: Only root can shut a system down.\n", + argv[0]); exit(1); } #endif @@ -98,7 +121,10 @@ main(argc, argv) if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */ prog = argv[0]; if((ptr = strrchr(argv[0], '/'))) prog = ++ptr; - + + /* All names (halt, reboot, fasthalt, fastboot, shutdown) + refer to the same program with the same options, + only the defaults differ. */ if(!strcmp("halt", prog)) { opt_reboot = 0; opt_quiet = 1; @@ -114,78 +140,105 @@ main(argc, argv) opt_quiet = 1; opt_fast = 0; timeout = 0; - if(argc > 1 && !strcmp(argv[1], "-s")) opt_single = 1; } else if(!strcmp("fastboot", prog)) { opt_reboot = 1; opt_quiet = 1; opt_fast = 1; timeout = 0; - if(argc > 1 && !strcmp(argv[1], "-s")) opt_single = 1; } else { /* defaults */ opt_reboot = 0; opt_quiet = 0; opt_fast = 0; timeout = 2*60; + } - c = 0; - while(++c < argc) { - if(argv[c][0] == '-') { - for(i = 1; argv[c][i]; i++) { + c = 0; + while(++c < argc) { + if(argv[c][0] == '-') { + for(i = 1; argv[c][i]; i++) { switch(argv[c][i]) { - case 'h': - opt_reboot = 0; - break; - case 'r': - opt_reboot = 1; - break; - case 'f': - opt_fast = 1; - break; - case 'q': - opt_quiet = 1; - break; - case 's': - opt_single = 1; - break; + case 'C': + opt_use_config_file = 1; + break; + case 'h': + opt_reboot = 0; + break; + case 'r': + opt_reboot = 1; + break; + case 'f': + opt_fast = 1; + break; + case 'q': + opt_quiet = 1; + break; + case 's': + opt_single = 1; + break; - default: - usage(); + default: + usage(); } - } - } else if(!strcmp("now", argv[c])) { - timeout = 0; - } else if(argv[c][0] == '+') { - timeout = 60 * atoi(&argv[c][1]); - } else if (isdigit(argv[c][0])) { - char *colon; - int hour = 0; - int minute = 0; - time_t tics; - struct tm *tt; - int now, then; + } + } else if(!strcmp("now", argv[c])) { + timeout = 0; + } else if(argv[c][0] == '+') { + timeout = 60 * atoi(&argv[c][1]); + } else if (isdigit(argv[c][0])) { + char *colon; + int hour = 0; + int minute = 0; + time_t tics; + struct tm *tt; + int now, then; - if((colon = strchr(argv[c], ':'))) { - *colon = '\0'; - hour = atoi(argv[c]); - minute = atoi(++colon); - } else usage(); + if((colon = strchr(argv[c], ':'))) { + *colon = '\0'; + hour = atoi(argv[c]); + minute = atoi(++colon); + } else usage(); - (void) time(&tics); - tt = localtime(&tics); + (void) time(&tics); + tt = localtime(&tics); - now = 3600 * tt->tm_hour + 60 * tt->tm_min; - then = 3600 * hour + 60 * minute; - timeout = then - now; - if(timeout < 0) { - fprintf(stderr, "That must be tomorrow, can't you wait till then?\n"); - exit(1); - } - } else { - strncpy(message, argv[c], sizeof(message)); - message[sizeof(message)-1] = '\0'; - opt_msgset = 1; + now = 3600 * tt->tm_hour + 60 * tt->tm_min; + then = 3600 * hour + 60 * minute; + timeout = then - now; + if(timeout < 0) { + fprintf(stderr, "That must be tomorrow, " + "can't you wait till then?\n"); + exit(1); + } + } else { + strncpy(message, argv[c], sizeof(message)); + message[sizeof(message)-1] = '\0'; + opt_msgset = 1; + } + } + + halt_action[0] = 0; + + /* No doubt we shall want to extend this some day + and register a series of commands to be executed + at various points during the shutdown sequence, + and to define the number of milliseconds to sleep, etc. */ + if (opt_use_config_file) { + char line[256], *p; + FILE *fp; + + /* Read and parse the config file */ + halt_action[0] = '\0'; + if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) { + if (fgets (line, sizeof(line), fp) != NULL && + strncasecmp (line, "HALT_ACTION", 11) == 0 && + iswhitespace(line[11])) { + p = line+11; + while(iswhitespace(*p)) + p++; + strcpy(halt_action, p); } + fclose (fp); } } @@ -212,6 +265,7 @@ main(argc, argv) /* so much for option-processing, now begin termination... */ if(!(whom = getlogin())) whom = "ghost"; + if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */ setpriority(PRIO_PROCESS, 0, PRIO_MIN); signal(SIGINT, int_handler); @@ -261,7 +315,8 @@ main(argc, argv) kill(1, SIGTSTP); /* tell init not to spawn more getty's */ write_wtmp(); if(opt_single) - close(open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)); + if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0) + close(fd); sync(); @@ -272,7 +327,7 @@ main(argc, argv) #ifndef DEBUGGING /* a gentle kill of all other processes except init */ kill(-1, SIGTERM); - sleep(2); + sleep(2); /* default 2, some people need 5 */ /* now use brute force... */ kill(-1, SIGKILL); @@ -292,14 +347,14 @@ main(argc, argv) sleep(1); if(opt_reboot) { - reboot(0xfee1dead, 672274793, 0x1234567); + my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ + my_puts("\nWhy am I still alive after reboot?"); } else { - freopen(_PATH_CONSOLE, "w", stdout); - printf("\nNow you can turn off the power...\n"); - fflush(stdout); + my_puts("\nNow you can turn off the power..."); + /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */ - reboot(0xfee1dead, 672274793, 0x89abcdef); - reboot(0xfee1dead, 672274793, 0xcdef0123); + my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ + do_halt(halt_action); } /* NOTREACHED */ exit(0); /* to quiet gcc */ @@ -307,6 +362,31 @@ main(argc, argv) /*** end of main() ***/ +void +do_halt(char *action) { + if (strcasecmp (action, "power_off") == 0) { + printf("Calling kernel power-off facility...\n"); + fflush(stdout); + my_reboot(LINUX_REBOOT_CMD_POWER_OFF); + printf("Error powering off\t%s\n", ERRSTRING); + fflush(stdout); + sleep (2); + } else + + /* This should be improved; e.g. Mike Jagdis wants "/sbin/mdstop -a" */ + /* Maybe we should also fork and wait */ + if (action[0] == '/') { + printf("Executing the program \"%s\" ...\n", action); + fflush(stdout); + execl(action, action, NULL); + printf("Error executing\t%s\n", ERRSTRING); + fflush(stdout); + sleep (2); + } + + my_reboot(LINUX_REBOOT_CMD_HALT); /* RB_HALT_SYSTEM */ +} + void write_user(struct utmp *ut) { @@ -319,7 +399,7 @@ write_user(struct utmp *ut) (void) strncat(term, ut->ut_line, sizeof(ut->ut_line)); /* try not to get stuck on a mangled ut_line entry... */ - if((fd = open(term, O_RDWR|O_NONBLOCK)) < 0) + if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0) return; sprintf(msg, "\007\r\nURGENT: broadcast message from %s:\r\n", whom); @@ -393,7 +473,7 @@ swap_off() sync(); if ((pid = fork()) < 0) { - printf("Cannot fork for swapoff. Shrug!\n"); + my_puts("Cannot fork for swapoff. Shrug!"); return; } if (!pid) { @@ -401,7 +481,8 @@ swap_off() execl("/etc/swapoff", SWAPOFF_ARGS, NULL); execl("/bin/swapoff", SWAPOFF_ARGS, NULL); execlp("swapoff", SWAPOFF_ARGS, NULL); - puts("Cannot exec swapoff, hoping umount will do the trick."); + my_puts("Cannot exec swapoff, " + "hoping umount will do the trick."); exit(0); } while ((result = wait(&status)) != -1 && result != pid) @@ -419,20 +500,20 @@ unmount_disks() sync(); if ((pid = fork()) < 0) { - printf("Cannot fork for umount, trying manually.\n"); + my_puts("Cannot fork for umount, trying manually."); unmount_disks_ourselves(); return; } if (!pid) { execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL); - printf("Cannot exec %s, trying umount.\n", _PATH_UMOUNT); + my_puts("Cannot exec " _PATH_UMOUNT ", trying umount."); execlp("umount", UMOUNT_ARGS, NULL); - puts("Cannot exec umount, giving up on umount."); + my_puts("Cannot exec umount, giving up on umount."); exit(0); } while ((result = wait(&status)) != -1 && result != pid) ; - puts("Unmounting any remaining filesystems..."); + my_puts("Unmounting any remaining filesystems..."); unmount_disks_ourselves(); } @@ -450,7 +531,7 @@ unmount_disks_ourselves() sync(); if (!(mtab = setmntent(_PATH_MTAB, "r"))) { - printf("shutdown: Cannot open %s.\n", _PATH_MTAB); + my_puts("shutdown: Cannot open " _PATH_MTAB "."); return; } n = 0; diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c index 14d8cfad..1664404c 100644 --- a/login-utils/simpleinit.c +++ b/login-utils/simpleinit.c @@ -16,10 +16,11 @@ #include #include #ifdef SHADOW_PWD -#include +# include #endif - +#include "my_crypt.h" #include "pathnames.h" +#include "linux_reboot.h" #define CMDSIZ 150 /* max size of a line in inittab */ #define NUMCMD 30 /* max number of lines in inittab */ @@ -411,13 +412,14 @@ void int_handler() sync(); sync(); - if((pid = fork()) == 0) { - /* reboot properly... */ + pid = fork(); + if (pid > 0) + return; + if (pid == 0) /* reboot properly... */ execl(_PATH_REBOOT, _PATH_REBOOT, (char *)0); - reboot(0xfee1dead, 672274793, 0x1234567); - } else if(pid < 0) - /* fork failed, try the hard way... */ - reboot(0xfee1dead, 672274793, 0x1234567); + + /* fork or exec failed, try the hard way... */ + my_reboot(LINUX_REBOOT_CMD_RESTART); } void set_tz() diff --git a/login-utils/vipw.c b/login-utils/vipw.c index a5763b10..50270a6e 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -190,15 +190,14 @@ pw_unlock() void -pw_edit(notsetuid) - int notsetuid; +pw_edit(int notsetuid) { int pstat; pid_t pid; char *p, *editor; if (!(editor = getenv("EDITOR"))) - editor = _PATH_VI; + editor = strdup(_PATH_VI); /* adia@egnatia.ee.auth.gr */ if ((p = strrchr(strtok(editor," \t"), '/')) != NULL) ++p; else diff --git a/misc-utils/Makefile b/misc-utils/Makefile index e33165f7..9ccf489b 100644 --- a/misc-utils/Makefile +++ b/misc-utils/Makefile @@ -31,9 +31,10 @@ USRBIN:=$(USRBIN) reset MAN1:=$(MAN1) reset.1 endif -# ifeq "$(HAVE_SYSVINIT)" "no" -# USRBIN:=$(USRBIN) pidof -# endif +# For script only +ifeq "$(HAVE_OPENPTY)" "yes" +CFLAGS:=$(CFLAGS) -DHAVE_OPENPTY +endif # Programs requiring special compilation @@ -58,16 +59,16 @@ endif # Rules for everything else -cal: cal.o $(BSD)/getopt.o $(BSD)/err.o +cal: cal.o $(ERR_O) chkdupexe: chkdupexe.pl clear: clear.sh kill: kill.o procs.o -logger: logger.o $(BSD)/getopt.o +logger: logger.o mcookie: mcookie.o md5.o mcookie.o: mcookie.c md5.h md5.o: md5.c md5.h reset: reset.sh -# pidof: pidof.o procs.o + ifeq "$(HAVE_NCURSES)" "yes" setterm: setterm.o endif diff --git a/misc-utils/cal.1 b/misc-utils/cal.1 index 80d95b27..9d41dc5e 100644 --- a/misc-utils/cal.1 +++ b/misc-utils/cal.1 @@ -42,7 +42,7 @@ .Nd displays a calendar .Sh SYNOPSIS .Nm cal -.Op Fl jy +.Op Fl mjy .Op Ar month Op Ar year .Sh DESCRIPTION .Nm Cal @@ -51,6 +51,8 @@ If arguments are not specified, the current month is displayed. The options are as follows: .Bl -tag -width Ds +.It Fl m +Display monday as the first day of the week. .It Fl j Display julian dates (days one-based, numbered from January 1). .It Fl y diff --git a/misc-utils/cal.c b/misc-utils/cal.c index 9d44d327..ab642014 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -34,6 +34,10 @@ * SUCH DAMAGE. */ +/* 1999-02-01 Jean-Francois Bignolles: added option '-m' to display + * monday as the first day of the week. + */ + /* This defines _LINUX_C_LIB_VERSION_MAJOR, dunno about gnulibc. We don't want it to read /usr/i586-unknown-linux/include/_G_config.h so we specify fill path. Were we got /usr/i586-unknown-linux from? @@ -72,7 +76,7 @@ #define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */ #define NUMBER_MISSING_DAYS 11 /* 11 day correction */ -#define MAXDAYS 42 /* max slots in a month array */ +#define MAXDAYS 43 /* max slots in a month array */ #define SPACE -1 /* used in day array */ static int days_in_month[2][13] = { @@ -87,6 +91,7 @@ int sep1752[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, + SPACE }, j_sep1752[MAXDAYS] = { SPACE, SPACE, 245, 246, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, @@ -94,6 +99,7 @@ int sep1752[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, + SPACE }, empty[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, @@ -101,10 +107,13 @@ int sep1752[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, + SPACE }; char day_headings[] = " S M Tu W Th F S "; +/* week1stday = 1 => " M Tu W Th F S S " */ char j_day_headings[] = " S M Tu W Th F S "; +/* week1stday = 1 => " M Tu W Th F S S " */ const char *full_month[12]; /* leap year -- account for gregorian reformation in 1752 */ @@ -124,6 +133,8 @@ const char *full_month[12]; #define leap_years_since_year_1(yr) \ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) +/* 0 => sunday (default), 1 => monday */ +int week1stday; int julian; void ascii_day __P((char *, int)); @@ -153,10 +164,12 @@ main(argc, argv) #endif setlocale(LC_ALL,""); - headers_init(); yflag = 0; - while ((ch = getopt(argc, argv, "jy")) != EOF) + while ((ch = getopt(argc, argv, "mjy")) != EOF) switch(ch) { + case 'm': + week1stday = 1; + break; case 'j': julian = 1; break; @@ -190,6 +203,7 @@ main(argc, argv) default: usage(); } + headers_init(); if (month) monthly(month, year); @@ -209,22 +223,28 @@ main(argc, argv) void headers_init(void) { - int i; + int i, wd; strcpy(day_headings,""); strcpy(j_day_headings,""); - - for(i = 0 ; i < 7 ; i++ ) { + #if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1) - strncat(day_headings,nl_langinfo(ABDAY_1+i),2); - strcat(j_day_headings,nl_langinfo(ABDAY_1+i)); +# define weekday(wd) nl_langinfo(ABDAY_1+wd) #else - strncat(day_headings,_time_info->abbrev_wkday[i],2); - strcat(j_day_headings,_time_info->abbrev_wkday[i]); +# define weekday(wd) _time_info->abbrev_wkday[wd] #endif + + for(i = 0 ; i < 7 ; i++ ) { + wd = (i + week1stday) % 7; + strncat(day_headings,weekday(wd),2); + strcat(j_day_headings,weekday(wd)); + if (strlen(weekday(wd)) == 2) + strcat(j_day_headings," "); strcat(day_headings," "); strcat(j_day_headings," "); } + +#undef weekday for (i = 0; i < 12; i++) { #if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1) @@ -341,15 +361,16 @@ day_array(month, year, days) int *days; { int day, dw, dm; + int *d_sep1752; if (month == 9 && year == 1752) { - memmove(days, - julian ? j_sep1752 : sep1752, MAXDAYS * sizeof(int)); + d_sep1752 = julian ? j_sep1752 : sep1752; + memcpy(days, d_sep1752 + week1stday, MAXDAYS * sizeof(int)); return; } - memmove(days, empty, MAXDAYS * sizeof(int)); + memcpy(days, empty, MAXDAYS * sizeof(int)); dm = days_in_month[leap_year(year)][month]; - dw = day_in_week(1, month, year); + dw = (day_in_week(1, month, year) - week1stday + 7) % 7; day = julian ? day_in_year(1, month, year) : 1; while (dm--) days[dw++] = day++; @@ -466,6 +487,6 @@ void usage() { - (void)fprintf(stderr, "usage: cal [-jy] [[month] year]\n"); + (void)fprintf(stderr, "usage: cal [-mjy] [[month] year]\n"); exit(1); } diff --git a/misc-utils/chkdupexe.pl b/misc-utils/chkdupexe.pl old mode 100644 new mode 100755 index f6111def..82ee9e98 --- a/misc-utils/chkdupexe.pl +++ b/misc-utils/chkdupexe.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl5 -w +#!/usr/bin/perl -w # # chkdupexe version 2.1.1 # @@ -27,7 +27,7 @@ $execdirs='/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin '. '/usr/X11/bin /usr/bin/X11 /usr/local/X11/bin '. '/usr/TeX/bin /usr/tex/bin /usr/games '. - '/usr/local/games /usr/intervies/bin/LINUX'; + '/usr/local/games'; # Values from /usr/include/linux/errno.h. Existence of linux/errno.ph is not # something to count on... :-( @@ -96,6 +96,8 @@ while (($prog,$paths)=each %progs) { } close(LS); +exit 0; + @unchecked=(); # Check if the users PATH contains something I've not checked. The site admin # might want to know about inconsistencies in user PATHs and chkdupexec @@ -108,6 +110,6 @@ foreach $dir (split(/:/,$ENV{'PATH'})) { $didthis{$device,$inode}=1; } -print "Warning: Your path contanis these directories which chkdupexe have not checked:\n",join(',',@unchecked), +print "Warning: Your path contains these directories which chkdupexe has not checked:\n",join(',',@unchecked), ".\nPlease review the execdirs list in chkdupexe.\n" if ($#unchecked>=$[); diff --git a/misc-utils/ddate.1 b/misc-utils/ddate.1 index 1ccc201f..7d17c824 100644 --- a/misc-utils/ddate.1 +++ b/misc-utils/ddate.1 @@ -43,8 +43,8 @@ Newline .IP %t Tab .IP %X -Number of days remaining until X-Day. (Not valid if the SubGenius options are not -compiled in.) +Number of days remaining until X-Day. (Not valid if the SubGenius options +are not compiled in.) .IP %{ .IP %} Used to enclose the part of the string which is to be replaced with the @@ -80,6 +80,12 @@ will produce undefined behaviour if asked to produce the date for St. Tib's day and its format string does not contain the St. Tib's Day delimiters %{ and %}. +.SH NOTE + +After `X-Day' passed without incident, the Church of the SubGenius +declared that it had got the year upside down - X-Day is actually in 8661 AD +rather than 1998 AD. Thus, the True X-Day is Cfn 40, 9827. + .SH AUTHOR .nh Original program by Druel the Chaotic aka Jeremy Johnson (mpython@gnu.ai.mit.edu) @@ -96,6 +102,8 @@ Public domain. All rites reversed. date(1), .br +http://www.subgenius.com/ +.br Malaclypse the Younger, .I "Principia Discordia, Or How I Found Goddess And What I Did To Her When I Found Her" diff --git a/misc-utils/ddate.c b/misc-utils/ddate.c index f838d1c6..09704e0b 100644 --- a/misc-utils/ddate.c +++ b/misc-utils/ddate.c @@ -307,12 +307,20 @@ struct disc_time convert(int nday, int nyear) #ifdef KILL_BOB -/* Code for counting down to X-Day, X-Day being Cfn 40, 3164 */ +/* Code for counting down to X-Day, X-Day being Cfn 40, 3164 + * + * After `X-Day' passed without incident, the CoSG declared that it had + * got the year upside down --- X-Day is actually in 8661 AD rather than + * 1998 AD. + * + * Thus, the True X-Day is Cfn 40, 9827. + * + */ int xday_countdown(int yday, int year) { int r=(185-yday)+(((yday<59)&&(leapp(year)))?1:0); - while(year<3164) r+=(leapp(++year)?366:365); - while(year>3164) r-=(leapp(year--)?366:365); + while(year<9827) r+=(leapp(++year)?366:365); + while(year>9827) r-=(leapp(year--)?366:365); return r; } diff --git a/misc-utils/hostname.c.orig b/misc-utils/hostname.c.orig deleted file mode 100644 index b7e61d1f..00000000 --- a/misc-utils/hostname.c.orig +++ /dev/null @@ -1,187 +0,0 @@ -/* hostname -- set the host name or show the host/domain name - - Copyright (C) 1994 Peter Tobias - - 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 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -#include -#include -#include -#include -#include -#include -#include - -#define NO_OPT -1 - -static char *program_name; -static const char *version_string = "hostname 1.5"; - -static void sethname(char *); -static void showhname(char *, int); -static void usage(void); - -static void sethname(char *hname) -{ - if(sethostname(hname, strlen(hname))) { - switch(errno) { - case EPERM: - fprintf(stderr,"%s: you must be root to change the host name\n", program_name); - break; - case EINVAL: - fprintf(stderr,"%s: name too long\n", program_name); - break; - default: - } - exit(1); - }; -} - -static void showhname(char *hname, int c) -{ - struct hostent *hp; - register char *p; - - if (!(hp = gethostbyname(hname))) { - herror(program_name); - exit(1); - } - - if (!(p = strchr(hp->h_name, '.'))) { - fprintf(stderr,"%s: can't find a FQDN for the host name `%s'\n", program_name, hname); - exit(1); - } - - switch(c) { - case 'd': - printf("%s\n", ++p); - break; - case 'f': - printf("%s\n", hp->h_name); - break; - case 's': - *p = '\0'; - printf("%s\n", hp->h_name); - break; - default: - } -} - -static void usage(void) -{ - printf("Usage: %s [OPTION]... [hostname]\n\n\ - -d, --domain display the DNS domain name\n\ - -F, --file filename read the host name from file\n\ - -f, --fqdn, --long display the long host name (FQDN)\n\ - -s, --short display the short host name\n\ - -h, --help display this help and exit\n\ - -v, --version output version information and exit\n\ -\n\ - When the program is called without any arguments, it displays the\n\ - current host name as set by the hostname command. If an argument\n\ - is given, the program will set the value of the host name to the\n\ - value specified.\n\ - Unless you are using bind or NIS for host lookups you can change the\n\ - FQDN (Fully Qualified Domain Name) and the DNS domain name (which is\n\ - part of the FQDN) in the /etc/hosts file.\n", program_name); -} - -int main(int argc, char **argv) -{ - int c; - int option_index = 0; - - char myname[MAXHOSTNAMELEN+1]; - - static const struct option long_options[] = - { - {"domain", no_argument, 0, 'd'}, - {"file", required_argument, 0, 'F'}, - {"fqdn", no_argument, 0, 'f'}, - {"help", no_argument, 0, 'h'}, - {"long", no_argument, 0, 'f'}, - {"short", no_argument, 0, 's'}, - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - - program_name = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0]; - - if (strcmp(program_name, "dnsdomainname") == 0) { - if (argc > 1) { - fprintf(stderr,"%s: You can't change the DNS domainname with this command\n", program_name); - fprintf(stderr,"\nUnless you are using bind or NIS for host lookups you can change the DNS\n"); - fprintf(stderr,"domain name (which is part of the FQDN) in the /etc/hosts file.\n"); - exit(1); - } - c = 'd'; - } else - c = getopt_long(argc, argv, "dfF:hsv", long_options, &option_index); - - gethostname(myname, sizeof(myname)); - - switch(c) - { - case 'd': - case 'f': - case 's': - showhname(myname, c); - break; - case 'F': - { - register FILE *fd; - register char *p; - char fline[MAXHOSTNAMELEN]; - - if ((fd = fopen(optarg, "r")) != NULL) { - while (fgets(fline, sizeof(fline), fd) != NULL) - if ((p = index(fline, '\n')) != NULL) { - *p = '\0'; - if (fline[0] == '#') - continue; - sethname(fline); - } - (void) fclose(fd); - } else { - fprintf(stderr,"%s: can't open `%s'\n", - program_name, optarg); - exit(1); - } - } - break; - case 'h': - usage(); - break; - case 'v': - printf("%s\n", version_string); - break; - case '?': - fprintf(stderr,"Try `%s --help' for more information.\n", program_name); - exit(1); - break; - case NO_OPT: - if (optind < argc) { - sethname(argv[optind]); - exit(0); - } - default: - printf("%s\n", myname); - - }; - exit(0); -} diff --git a/misc-utils/kill.c b/misc-utils/kill.c index 85911211..62993813 100644 --- a/misc-utils/kill.c +++ b/misc-utils/kill.c @@ -43,20 +43,91 @@ #include #include -#ifdef __linux__ -/* - * sys_signame -- an ordered list of signals. - * lifted from /usr/include/linux/signal.h - * this particular order is only correct for linux. - * this is _not_ portable. - */ -char *sys_signame[NSIG] = { - "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "UNUSED", - "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", - "STKFLT","CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "IO", - "XCPU", "XFSZ", "VTALRM","PROF", "WINCH", NULL -}; +#define SIZE(a) (sizeof(a)/sizeof(a[0])) + +struct signv { + char *name; + int val; +} sys_signame[] = { + /* POSIX signals */ + { "HUP", SIGHUP }, /* 1 */ + { "INT", SIGINT }, /* 2 */ + { "QUIT", SIGQUIT }, /* 3 */ + { "ILL", SIGILL }, /* 4 */ + { "ABRT", SIGABRT }, /* 6 */ + { "FPE", SIGFPE }, /* 8 */ + { "KILL", SIGKILL }, /* 9 */ + { "SEGV", SIGSEGV }, /* 11 */ + { "PIPE", SIGPIPE }, /* 13 */ + { "ALRM", SIGALRM }, /* 14 */ + { "TERM", SIGTERM }, /* 15 */ + { "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */ + { "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */ + { "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */ + { "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */ + { "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */ + { "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */ + { "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */ + { "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */ + /* Miscellaneous other signals */ +#ifdef SIGTRAP + { "TRAP", SIGTRAP }, /* 5 */ +#endif +#ifdef SIGIOT + { "IOT", SIGIOT }, /* 6, same as SIGABRT */ +#endif +#ifdef SIGEMT + { "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */ +#endif +#ifdef SIGBUS + { "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */ +#endif +#ifdef SIGSYS + { "SYS", SIGSYS }, /* 12 (mips,alpha,sparc*) */ +#endif +#ifdef SIGSTKFLT + { "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */ +#endif +#ifdef SIGURG + { "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */ +#endif +#ifdef SIGIO + { "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */ +#endif +#ifdef SIGPOLL + { "POLL", SIGPOLL }, /* same as SIGIO */ +#endif +#ifdef SIGCLD + { "CLD", SIGCLD }, /* same as SIGCHLD (mips) */ +#endif +#ifdef SIGXCPU + { "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */ #endif +#ifdef SIGXFSZ + { "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */ +#endif +#ifdef SIGVTALRM + { "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */ +#endif +#ifdef SIGPROF + { "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */ +#endif +#ifdef SIGPWR + { "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */ +#endif +#ifdef SIGINFO + { "INFO", SIGINFO }, /* 29 (alpha) */ +#endif +#ifdef SIGLOST + { "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */ +#endif +#ifdef SIGWINCH + { "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */ +#endif +#ifdef SIGUNUSED + { "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */ +#endif +}; int main (int argc, char *argv[]); extern char *mybasename(char *); @@ -197,9 +268,9 @@ int signame_to_signum (char *sig) if (! strncasecmp (sig, "sig", 3)) sig += 3; - for (n = 1; (n < NSIG) && (sys_signame[n] != NULL); n++) { - if (! strcasecmp (sys_signame[n], sig)) - return n; + for (n = 0; n < SIZE(sys_signame); n++) { + if (! strcasecmp (sys_signame[n].name, sig)) + return sys_signame[n].val; } return (-1); } @@ -226,22 +297,33 @@ void nosig (char *name) void printsig (int sig) { - printf ("%s\n", sys_signame[sig]); + int n; + + for (n = 0; n < SIZE(sys_signame); n++) { + if (sys_signame[n].val == sig) { + printf ("%s\n", sys_signame[n].name); + return; + } + } + printf("%d\n", sig); } void printsignals (FILE *fp) { - int n; + int n, lth; + int lpos = 0; - for (n = 1; (n < NSIG) && (sys_signame[n] != NULL); n++) { - fputs (sys_signame[n], fp); - if (n == (NSIG / 2) || n == (NSIG - 1)) + for (n = 0; n < SIZE(sys_signame); n++) { + lth = 1+strlen(sys_signame[n].name); + if (lpos+lth > 72) { fputc ('\n', fp); - else + lpos = 0; + } else if (lpos) fputc (' ', fp); + lpos += lth; + fputs (sys_signame[n].name, fp); } - if (n < (NSIG - 1)) - fputc ('\n', fp); + fputc ('\n', fp); } int usage (int status) diff --git a/misc-utils/look.c b/misc-utils/look.c index 1d2848b5..72256c19 100644 --- a/misc-utils/look.c +++ b/misc-utils/look.c @@ -54,42 +54,36 @@ #include #include #include +#include #include "pathnames.h" -/* - * FOLD and DICT convert characters to a normal form for comparison, - * according to the user specified flags. - * - * DICT expects integers because it uses a non-character value to - * indicate a character which should not participate in comparisons. - */ #define EQUAL 0 #define GREATER 1 #define LESS (-1) -#define NO_COMPARE (-2) - -#define FOLD(c) (isascii(c) && isupper(c) ? tolower(c) : (c)) -#define DICT(c) (isascii(c) && isalnum(c) ? (c) : NO_COMPARE) int dflag, fflag; +/* uglified the source a bit with globals, so that we only need + to allocate comparbuf once */ +int stringlen; +char *string; +char *comparbuf; -char *binary_search __P((char *, char *, char *)); -int compare __P((char *, char *, char *)); -void err __P((const char *fmt, ...)); -char *linear_search __P((char *, char *, char *)); -int look __P((char *, char *, char *)); -void print_from __P((char *, char *, char *)); - -static void usage __P((void)); +static char *binary_search (char *, char *); +static int compare (char *, char *, int); +static void err (const char *fmt, ...); +static char *linear_search (char *, char *); +static int look (char *, char *); +static void print_from (char *, char *); +static void usage (void); -void -main(argc, argv) - int argc; - char *argv[]; +int +main(int argc, char *argv[]) { struct stat sb; int ch, fd, termchar; - char *back, *file, *front, *string, *p; + char *back, *file, *front, *p; + + setlocale(LC_ALL, ""); file = _PATH_WORDS; termchar = '\0'; @@ -142,32 +136,35 @@ main(argc, argv) (off_t)0)) <= (void *)0) err("%s: %s", file, strerror(errno)); back = front + sb.st_size; - exit(look(string, front, back)); + return look(front, back); } int -look(string, front, back) - char *string, *front, *back; +look(char *front, char *back) { - register int ch; - register char *readp, *writep; + int ch; + char *readp, *writep; /* Reformat string string to avoid doing it multiple times later. */ - for (readp = writep = string; (ch = *readp++) != 0;) { - if (fflag) - ch = FOLD(ch); - if (dflag) - ch = DICT(ch); - if (ch != NO_COMPARE) - *(writep++) = ch; - } - *writep = '\0'; + if (dflag) { + for (readp = writep = string; (ch = *readp++) != 0;) { + if (isalnum(ch)) + *(writep++) = ch; + } + *writep = '\0'; + stringlen = writep - string; + } else + stringlen = strlen(string); + + comparbuf = malloc(stringlen+1); + if (comparbuf == NULL) + err("Out of memory"); - front = binary_search(string, front, back); - front = linear_search(string, front, back); + front = binary_search(front, back); + front = linear_search(front, back); if (front) - print_from(string, front, back); + print_from(front, back); return (front ? 0 : 1); } @@ -214,10 +211,9 @@ look(string, front, back) while (p < back && *p++ != '\n'); char * -binary_search(string, front, back) - register char *string, *front, *back; +binary_search(char *front, char *back) { - register char *p; + char *p; p = front + (back - front) / 2; SKIP_PAST_NEWLINE(p, back); @@ -227,7 +223,7 @@ binary_search(string, front, back) * infinitely loop. */ while (p < back && back > front) { - if (compare(string, p, back) == GREATER) + if (compare(p, back, 1) == GREATER) front = p; else back = p; @@ -249,11 +245,10 @@ binary_search(string, front, back) * o front is before or at the first line to be printed. */ char * -linear_search(string, front, back) - char *string, *front, *back; +linear_search(char *front, char *back) { while (front < back) { - switch (compare(string, front, back)) { + switch (compare(front, back, 1)) { case EQUAL: /* Found it. */ return (front); break; @@ -272,20 +267,26 @@ linear_search(string, front, back) * Print as many lines as match string, starting at front. */ void -print_from(string, front, back) - register char *string, *front, *back; +print_from(char *front, char *back) { - for (; front < back && compare(string, front, back) == EQUAL; ++front) { - for (; front < back && *front != '\n'; ++front) - if (putchar(*front) == EOF) - err("stdout: %s", strerror(errno)); - if (putchar('\n') == EOF) - err("stdout: %s", strerror(errno)); + int eol; + + while (front < back && compare(front, back, 1) == EQUAL) { + if (compare(front, back, fflag) == EQUAL) { + eol = 0; + while (front < back && !eol) { + if (putchar(*front) == EOF) + err("stdout: %s", strerror(errno)); + if (*front++ == '\n') + eol = 1; + } + } else + SKIP_PAST_NEWLINE(front, back); } } /* - * Return LESS, GREATER, or EQUAL depending on how the string1 compares with + * Return LESS, GREATER, or EQUAL depending on how string compares with * string2 (s1 ??? s2). * * o Matches up to len(s1) are EQUAL. @@ -294,32 +295,34 @@ print_from(string, front, back) * Compare understands about the -f and -d flags, and treats comparisons * appropriately. * - * The string "s1" is null terminated. The string s2 is '\n' terminated (or - * "back" terminated). + * The string "string" is null terminated. The string "s2" is '\n' terminated + * (or "s2end" terminated). + * + * We use strcasecmp etc, since it knows how to ignore case also + * in other locales. */ int -compare(s1, s2, back) - register char *s1, *s2, *back; -{ - register int ch; - - for (; *s1 && s2 < back && *s2 != '\n';) { - ch = *s2; - if (fflag) - ch = FOLD(ch); - if (dflag) - ch = DICT(ch); - - if (ch == NO_COMPARE) { - ++s2; /* Ignore character in comparison. */ - continue; - } - if (*s1 != ch) - return (*s1 < ch ? LESS : GREATER); - ++s1; - ++s2; +compare(char *s2, char *s2end, int nocase) { + int i; + char *p; + + /* copy, ignoring things that should be ignored */ + p = comparbuf; + i = stringlen; + while(s2 < s2end && *s2 != '\n' && i--) { + if (!dflag || isalnum(*s2)) + *p++ = *s2; + s2++; } - return (*s1 ? GREATER : EQUAL); + *p = 0; + + /* and compare */ + if (nocase) + i = strncasecmp(comparbuf, string, stringlen); + else + i = strncmp(comparbuf, string, stringlen); + + return ((i > 0) ? LESS : (i < 0) ? GREATER : EQUAL); } static void diff --git a/misc-utils/mcookie.1 b/misc-utils/mcookie.1 index 6d3a11c3..c6667e21 100644 --- a/misc-utils/mcookie.1 +++ b/misc-utils/mcookie.1 @@ -19,10 +19,11 @@ process id, the parent process id, the contents of an input file (if .B \-f is specified), and several bytes of information from the first of the following devices which is present: -.IR /dev/urandom ", " /dev/random ", " /dev/audio . -Other files in -.I /proc -may be used as a last resort. +.IR /dev/random , +.IR /dev/urandom , +files in +.IR /proc , +.IR /dev/audio . .SH BUGS The entropy in the generated 128-bit is probably quite small (and, therefore, vulnerable to attack) unless a non-pseudorandom number generator diff --git a/misc-utils/mcookie.c b/misc-utils/mcookie.c index 05136190..33ae7630 100644 --- a/misc-utils/mcookie.c +++ b/misc-utils/mcookie.c @@ -101,9 +101,12 @@ int main( int argc, char **argv ) } for (i = 0; i < RNGS; i++) { - if ((fd = open( rngs[i].path, O_RDONLY )) >= 0) { + if ((fd = open( rngs[i].path, O_RDONLY|O_NONBLOCK )) >= 0) { r = read( fd, buf, sizeof( buf ) ); - MD5Update( &ctx, buf, r ); + if (r > 0) + MD5Update( &ctx, buf, r ); + else + r = 0; close( fd ); if (Verbose) fprintf( stderr, "Got %d bytes from %s\n", r, rngs[i].path ); diff --git a/misc-utils/procs.c b/misc-utils/procs.c index 2ea3e098..fd0e5add 100644 --- a/misc-utils/procs.c +++ b/misc-utils/procs.c @@ -6,9 +6,9 @@ * modify it under the terms of the gnu general public license. * there is no warranty. * - * $Author: janl $ - * $Revision: 1.5 $ - * $Date: 1996/11/11 22:40:03 $ + * faith + * 1.2 + * 1995/02/23 01:20:40 * */ @@ -112,7 +112,6 @@ static char *parse_parens (char *buf) return cp; } - char *mybasename (char *path) { char *cp; @@ -120,3 +119,4 @@ char *mybasename (char *path) cp = strrchr (path, '/'); return (cp ? cp + 1 : path); } + diff --git a/misc-utils/script.c b/misc-utils/script.c index af4013d3..23c48ea6 100644 --- a/misc-utils/script.c +++ b/misc-utils/script.c @@ -49,6 +49,10 @@ #include #endif +#ifdef HAVE_OPENPTY +#include +#endif + void done(void); void fail(void); void fixtty(void); @@ -70,10 +74,12 @@ struct termios tt; struct winsize win; int lb; int l; +#ifndef HAVE_OPENPTY char line[] = "/dev/ptyXX"; +#endif int aflg; -void +int main(argc, argv) int argc; char *argv[]; @@ -131,6 +137,8 @@ main(argc, argv) doshell(); } doinput(); + + return 0; } void @@ -140,6 +148,9 @@ doinput() char ibuf[BUFSIZ]; (void) fclose(fscript); +#ifdef HAVE_OPENPTY + (void) close(slave); +#endif while ((cc = read(0, ibuf, BUFSIZ)) > 0) (void) write(master, ibuf, cc); done(); @@ -170,6 +181,9 @@ dooutput() char obuf[BUFSIZ], *ctime(); (void) close(0); +#ifdef HAVE_OPENPTY + (void) close(slave); +#endif tvec = time((time_t *)NULL); fprintf(fscript, "Script started on %s", ctime(&tvec)); for (;;) { @@ -250,6 +264,14 @@ done() void getmaster() { +#ifdef HAVE_OPENPTY + (void) tcgetattr(0, &tt); + (void) ioctl(0, TIOCGWINSZ, (char *)&win); + if (openpty(&master, &slave, NULL, &tt, &win) < 0) { + fprintf(stderr, "openpty failed\n"); + fail(); + } +#else char *pty, *bank, *cp; struct stat stb; @@ -282,12 +304,13 @@ getmaster() } fprintf(stderr, "Out of pty's\n"); fail(); +#endif /* not HAVE_OPENPTY */ } void getslave() { - +#ifndef HAVE_OPENPTY line[strlen("/dev/")] = 't'; slave = open(line, O_RDWR); if (slave < 0) { @@ -296,6 +319,7 @@ getslave() } (void) tcsetattr(slave, TCSAFLUSH, &tt); (void) ioctl(slave, TIOCSWINSZ, (char *)&win); +#endif (void) setsid(); (void) ioctl(slave, TIOCSCTTY, 0); } diff --git a/misc-utils/setterm.c b/misc-utils/setterm.c index 49903f3b..3b3e6c24 100644 --- a/misc-utils/setterm.c +++ b/misc-utils/setterm.c @@ -95,6 +95,9 @@ #include #include #include +#ifndef NCURSES_CONST +#define NCURSES_CONST const /* define before including term.h */ +#endif #include #if NCH #include @@ -928,11 +931,12 @@ int vcterm; /* Set if terminal is a virtual console. */ /* -inversescreen [on|off]. Vc only (vt102). */ if (opt_inversescreen) { - if (vcterm) + if (vcterm) { if (opt_invsc_on) printf("\033[?5h"); else printf("\033[?5l"); + } } /* -bold [on|off]. Vc behaves as expected, otherwise off turns off diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c index 1a8e1edd..49419241 100644 --- a/misc-utils/whereis.c +++ b/misc-utils/whereis.c @@ -99,6 +99,8 @@ static char *bindirs[] = { "/usr/libexec", "/usr/share", + "/opt/*/bin", + 0 }; diff --git a/misc-utils/write.c b/misc-utils/write.c index e43b0bf9..07a113ea 100644 --- a/misc-utils/write.c +++ b/misc-utils/write.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ #ifdef __linux__ #include #include "pathnames.h" -#include #endif void search_utmp(char *, char *, char *, uid_t); @@ -67,7 +67,7 @@ int utmp_chk(char *, char *); extern int errno; -void +int main(int argc, char **argv) { register char *cp; @@ -77,9 +77,7 @@ main(int argc, char **argv) char tty[MAXPATHLEN], *mytty, *ttyname(); void done(); -#ifdef __linux__ setlocale(LC_CTYPE,""); -#endif /* check that sender has write enabled */ if (isatty(fileno(stdin))) @@ -143,6 +141,7 @@ main(int argc, char **argv) } done(); /* NOTREACHED */ + return 0; } @@ -291,11 +290,12 @@ void do_write(char *tty, char *mytty, uid_t myuid) void done(); /* Determine our login name before the we reopen() stdout */ - if ((login = getlogin()) == NULL) + if ((login = getlogin()) == NULL) { if ((pwd = getpwuid(myuid)) != NULL) login = pwd->pw_name; else login = "???"; + } if (strlen(tty) + 6 > sizeof(path)) exit(1); @@ -347,8 +347,13 @@ void wr_fputs(char *s) PUTC('\r'); PUTC('\n'); } else if (!isprint(c) && !isspace(c) && c != '\007') { - PUTC('^'); - PUTC(c^0x40); /* DEL to ?, others to alpha */ + if (c & 0x80) { + /* use some fallback? */ + (void)printf("\\%3o", (unsigned char) c); + } else { + PUTC('^'); + PUTC(c^0x40); /* DEL to ?, others to alpha */ + } } else PUTC(c); } diff --git a/mkminix-0.1/README b/mkminix-0.1/README new file mode 100644 index 00000000..d93c38e9 --- /dev/null +++ b/mkminix-0.1/README @@ -0,0 +1,47 @@ +Mkminix-0.1 by W. Black + +Description +----------- +This directory contains a hacked version of mkfs.minix from util-linux 2.8. +The hack in question was primarily a bit of #ifndef-ing to make it compile +successfully under DJGPP. Due to DOS's brain-damaged 8.3 filename limitation, +the executable has been renamed from mkfs.minix to mkminix.exe. +[Executable deleted in the util-linux distribution.] + +Distribution +------------ +This distribution should have come with both sources and executable. If +you're missing either, feel free to visit my site at +http://www.geocities.com/SiliconValley/Network/5508 to get a fresh one if +you need it. + +This program and its source program in util-linux are protected by the GNU +General Public License. See the file COPYING for details. + +Why +--- +Exactly why would anyone want to create a Minix filesystem under DOS? The +answer, as far as I am concerned, is in the interest of creating initial +ramdisks for Linux. By being able to configure an initrd from DOS (or Win +'95, etc.), you can make the transition to Linux that much easier (think +Win '95 autoplay Linux distributions, for example). + +Phase II of this project would logically be to be able to populate this initrd +with files. That is my goal for mkminix-0.2. + +Installation +------------ +At this point, everything is pretty much already installed. Just run MKMINIX +from the DOS prompt. The source will compile under DJGPP if and only if you +have a copy of linux/minix_fs.h. I included the one from Linux kernel 2.0.30, +but these files have a way of changing in annoying ways, so it's probably best +to use one that matches whatever version of Linux you are going to be running +concurrently. This is if you have to be ABSOLUTELY sure that everything +matches... BTW, compile line is as follows for DJGPP: + + gcc -o mkminix.exe mkminix.c + +Desperate Plea for Attention +---------------------------- +If you find this program useful (or silly, or a complete waste of time), please +drop me a line at wjblack@yahoo.com. Thanks! diff --git a/mkminix-0.1/linux/minix_fs.h b/mkminix-0.1/linux/minix_fs.h new file mode 100644 index 00000000..3bc020fc --- /dev/null +++ b/mkminix-0.1/linux/minix_fs.h @@ -0,0 +1,135 @@ +#ifndef _LINUX_MINIX_FS_H +#define _LINUX_MINIX_FS_H + +/* + * The minix filesystem constants/structures + */ + +/* + * Thanks to Kees J Bot for sending me the definitions of the new + * minix filesystem (aka V2) with bigger inodes and 32-bit block + * pointers. + */ + +#define MINIX_ROOT_INO 1 + +/* Not the same as the bogus LINK_MAX in . Oh well. */ +#define MINIX_LINK_MAX 250 + +#define MINIX_I_MAP_SLOTS 8 +#define MINIX_Z_MAP_SLOTS 64 +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_VALID_FS 0x0001 /* Clean fs. */ +#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ + +#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) +#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) + +#define MINIX_V1 0x0001 /* original minix fs */ +#define MINIX_V2 0x0002 /* minix V2 fs */ + +#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version + +/* + * This is the original minix inode layout on disk. + * Note the 8-bit gid and atime and ctime. + */ +struct minix_inode { + __u16 i_mode; + __u16 i_uid; + __u32 i_size; + __u32 i_time; + __u8 i_gid; + __u8 i_nlinks; + __u16 i_zone[9]; +}; + +/* + * The new minix inode has all the time entries, as well as + * long block numbers and a third indirect block (7+1+1+1 + * instead of 7+1+1). Also, some previously 8-bit values are + * now 16-bit. The inode is now 64 bytes instead of 32. + */ +struct minix2_inode { + __u16 i_mode; + __u16 i_nlinks; + __u16 i_uid; + __u16 i_gid; + __u32 i_size; + __u32 i_atime; + __u32 i_mtime; + __u32 i_ctime; + __u32 i_zone[10]; +}; + +/* + * minix super-block data on disk + */ +struct minix_super_block { + __u16 s_ninodes; + __u16 s_nzones; + __u16 s_imap_blocks; + __u16 s_zmap_blocks; + __u16 s_firstdatazone; + __u16 s_log_zone_size; + __u32 s_max_size; + __u16 s_magic; + __u16 s_state; + __u32 s_zones; +}; + +struct minix_dir_entry { + __u16 inode; + char name[0]; +}; + +#ifdef __KERNEL__ + +extern int minix_lookup(struct inode * dir,const char * name, int len, + struct inode ** result); +extern int minix_create(struct inode * dir,const char * name, int len, int mode, + struct inode ** result); +extern int minix_mkdir(struct inode * dir, const char * name, int len, int mode); +extern int minix_rmdir(struct inode * dir, const char * name, int len); +extern int minix_unlink(struct inode * dir, const char * name, int len); +extern int minix_symlink(struct inode * inode, const char * name, int len, + const char * symname); +extern int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len); +extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev); +extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len, + struct inode * new_dir, const char * new_name, int new_len, int must_be_dir); +extern struct inode * minix_new_inode(const struct inode * dir); +extern void minix_free_inode(struct inode * inode); +extern unsigned long minix_count_free_inodes(struct super_block *sb); +extern int minix_new_block(struct super_block * sb); +extern void minix_free_block(struct super_block * sb, int block); +extern unsigned long minix_count_free_blocks(struct super_block *sb); + +extern int minix_bmap(struct inode *,int); + +extern struct buffer_head * minix_getblk(struct inode *, int, int); +extern struct buffer_head * minix_bread(struct inode *, int, int); + +extern void minix_truncate(struct inode *); +extern void minix_put_super(struct super_block *); +extern struct super_block *minix_read_super(struct super_block *,void *,int); +extern int init_minix_fs(void); +extern void minix_write_super(struct super_block *); +extern int minix_remount (struct super_block * sb, int * flags, char * data); +extern void minix_read_inode(struct inode *); +extern void minix_write_inode(struct inode *); +extern void minix_put_inode(struct inode *); +extern void minix_statfs(struct super_block *, struct statfs *, int); +extern int minix_sync_inode(struct inode *); +extern int minix_sync_file(struct inode *, struct file *); + +extern struct inode_operations minix_file_inode_operations; +extern struct inode_operations minix_dir_inode_operations; +extern struct inode_operations minix_symlink_inode_operations; + +#endif /* __KERNEL__ */ + +#endif diff --git a/mkminix-0.1/mkmin-dj.h b/mkminix-0.1/mkmin-dj.h new file mode 100644 index 00000000..1ed7b216 --- /dev/null +++ b/mkminix-0.1/mkmin-dj.h @@ -0,0 +1,43 @@ +/* Stolen from linux/fs.h */ +#define BLOCK_SIZE 1024 + +/* Ugh */ +typedef unsigned char __u8; +typedef unsigned short __u16; +typedef unsigned int __u32; + +/* Stolen from linux/stat.h, since DJGPP's stat.h produces different values */ +#define S_IFMT 00170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) + +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 + +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 + +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 diff --git a/mkminix-0.1/mkminix.diff b/mkminix-0.1/mkminix.diff new file mode 100644 index 00000000..45d6c819 --- /dev/null +++ b/mkminix-0.1/mkminix.diff @@ -0,0 +1,46 @@ +48a49,51 +> * 09.29.98 - Modified to compile under DJGPP (minus mount-checking, etc.). +> * (wjblack@yahoo.com) +> * +69a73,78 +> +> /* DJGPP's IOCTL interface should probably not be trusted here. It's not +> needed, anyway. Nor does DJGPP have any clue about mounted filesystems. +> Oh, did I mention that the directory status, etc, doesn't match that of +> the Minix FS? */ +> #ifndef __DJGPP__ +74a84,91 +> #endif +> +> /* For those defs that DJGPP doesn't have (or has wrong) */ +> #ifdef __DJGPP__ +> #include "mkmin-dj.h" +> #endif +> +> /* DJGPP requires that you stick a linux/minix_fs.h somewhere appropriate */ +172a190 +> #ifndef __DJGPP__ +173a192,194 +> #else +> #define usage() fatal_error("Usage: %s [-c | -l filename] [-nXX] [-iXX] imagefile [blocks]\n",16) +> #endif +175a197 +> #ifndef __DJGPP__ +196a219 +> #endif /* __DJGPP__ */ +238a262 +> #ifndef __DJGPP__ +242a267 +> #endif +613a639 +> #ifndef __DJGPP__ +614a641 +> #endif +694a722 +> #ifndef __DJGPP__ +695a724 +> #endif +707a737 +> #ifndef __DJGPP__ +713a744 +> #endif diff --git a/mount/Makefile b/mount/Makefile index 32272a9b..c61b4ae8 100644 --- a/mount/Makefile +++ b/mount/Makefile @@ -3,18 +3,17 @@ include ../MCONFIG endif CC = gcc -CFLAGS = -O2 +CFLAGS = -I$(LIB) $(OPT) WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes DEFINES = -DHAVE_NFS -LDFLAGS = RPCSVCDIR = rpcsvc RPC_CFLAGS = -Wno-unused RPCGEN = rpcgen #INSTALL = install -#INSTALL_SUID = $(INSTALL) -m 4755 -o root -#INSTALL_PROG = $(INSTALL) -m 755 -#INSTALL_DATA = $(INSTALL) -m 644 +#INSTALLSUID = $(INSTALL) -m 4755 -o root +#INSTALLPROG = $(INSTALL) -m 755 +#INSTALLDATA = $(INSTALL) -m 644 ## for suid progs (mount, umount) #BINDIR = /bin @@ -54,32 +53,43 @@ install: $(PROGS) %.o: %.c $(COMPILE) $< -mount: mount.o fstab.o sundries.o realpath.o version.o $(NFS_OBJS) $(LO_OBJS) - $(LINK) $^ $(LDLIBS) -o $@ +mount: mount.o fstab.o sundries.o realpath.o mntent.o version.o \ + mount_guess_fstype.o mount_by_label.o getusername.o \ + $(LIB)/setproctitle.o $(NFS_OBJS) $(LO_OBJS) + $(LINK) $^ -o $@ -umount: umount.o fstab.o sundries.o realpath.o version.o $(LO_OBJS) - $(LINK) $^ $(LDLIBS) -o $@ +umount: umount.o fstab.o sundries.o realpath.o mntent.o getusername.o \ + version.o $(LO_OBJS) + $(LINK) $^ -o $@ swapon: swapon.o version.o - $(LINK) $^ $(LDLIBS) -o $@ + $(LINK) $^ -o $@ losetup: losetup.o - $(LINK) $^ $(LDLIBS) -o $@ - -mount.o: linux_fs.h + $(LINK) $^ -o $@ mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h mount.o umount.o fstab.o sundries.o: fstab.h +mount.o fstab.o mntent.o: mntent.h + +mount.o mount_guess_fstype.o: mount_guess_fstype.h + +mount.o: $(LIB)/setproctitle.h + +mount.o umount.o getusername.o: getusername.h + mount.o umount.o losetup.o lomount.o: lomount.h loop.h -swapon.o: swap.h swapargs.h +swapon.o: swap_constants.h swapargs.h sundries.o nfsmount.o nfsmount_xdr.o nfsmount_clnt.o: nfsmount.h umount.o: mount_constants.h +mount.o mount_by_label.o mount_guess_fstype.o: linux_fs.h + nfsmount_clnt.o: nfsmount_clnt.c $(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c @@ -109,11 +119,6 @@ nfs_mountversion.h: echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \ fi > nfs_mountversion.h -SWAPH=/usr/include/linux/swap.h -swap.h: - rm -f swap.h - if [ -f $(SWAPH) ]; then cp $(SWAPH) .; else touch swap.h; fi - swapargs.h: sh swap.configure @@ -122,7 +127,7 @@ loop.h: clean: rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff - rm -f swap.h loop.h nfs_mountversion.h + rm -f loop.h nfs_mountversion.h clobber distclean realclean: clean # rm -f $(GEN_FILES) diff --git a/mount/Makefile.standalone b/mount/Makefile.standalone index 2cedcd23..1be37568 100644 --- a/mount/Makefile.standalone +++ b/mount/Makefile.standalone @@ -5,7 +5,7 @@ # For now: a standalone version CC = gcc -CFLAGS = -O2 +CFLAGS = -O2 -I../lib #WARNFLAGS = -Wall -Wstrict-prototypes # We really want @@ -23,11 +23,11 @@ RPC_CFLAGS = -Wno-unused RPCGEN = rpcgen INSTALL = install -INSTALL_SUID = $(INSTALL) -m 4755 -o root -INSTALL_PROG = $(INSTALL) -m 755 -INSTALL_DATA = $(INSTALL) -m 644 -INSTALL_DIR = mkdir -p -INSTALL_MAN = $(INSTALL_DATA) +INSTALLSUID = $(INSTALL) -m 4755 -o root +INSTALLPROG = $(INSTALL) -m 755 +INSTALLDATA = $(INSTALL) -m 644 +INSTALLDIR = mkdir -p +INSTALLMAN = $(INSTALLDATA) MANDIR = /usr/man ## for suid progs (mount, umount) @@ -57,21 +57,22 @@ LO_OBJS=lomount.o all: $(PROGS) install: $(PROGS) - $(INSTALL_DIR) $(BINDIR) $(SBINDIR) - $(INSTALL_SUID) -s $(SUID_PROGS) $(BINDIR) - $(INSTALL_PROG) -s $(NOSUID_PROGS) $(SBINDIR) + $(INSTALLDIR) $(BINDIR) $(SBINDIR) + $(INSTALLSUID) -s $(SUID_PROGS) $(BINDIR) + $(INSTALLPROG) -s $(NOSUID_PROGS) $(SBINDIR) (cd $(SBINDIR); ln -sf swapon swapoff) - $(INSTALL_DIR) $(MANDIR)/man5 $(MANDIR)/man8 - $(INSTALL_MAN) $(MAN5) $(MANDIR)/man5 - $(INSTALL_MAN) $(MAN8) $(MANDIR)/man8 + $(INSTALLDIR) $(MANDIR)/man5 $(MANDIR)/man8 + $(INSTALLMAN) $(MAN5) $(MANDIR)/man5 + $(INSTALLMAN) $(MAN8) $(MANDIR)/man8 %.o: %.c $(COMPILE) $< -mount: mount.o fstab.o sundries.o realpath.o version.o $(NFS_OBJS) $(LO_OBJS) +mount: mount.o fstab.o sundries.o realpath.o mntent.o version.o \ + mount_guess_fstype.o mount_by_label.o ../lib/setproctitle.o $(NFS_OBJS) $(LO_OBJS) $(LINK) $^ -o $@ -umount: umount.o fstab.o sundries.o realpath.o version.o $(LO_OBJS) +umount: umount.o fstab.o sundries.o realpath.o mntent.o version.o $(LO_OBJS) $(LINK) $^ -o $@ swapon: swapon.o version.o @@ -84,14 +85,20 @@ mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h mount.o umount.o fstab.o sundries.o: fstab.h -mount.o umount.o losetup.o: lomount.h loop.h +mount.o fstab.o mntent.o: mntent.h -swapon.o: swap.h swapargs.h +mount.o mount_guess_fstype.o: mount_guess_fstype.h + +mount.o umount.o losetup.o lomount.o: lomount.h loop.h + +swapon.o: swap_constants.h swapargs.h sundries.o nfsmount.o nfsmount_xdr.o nfsmount_clnt.o: nfsmount.h umount.o: mount_constants.h +mount.o mount_by_label.o mount_guess_fstype.o: linux_fs.h + nfsmount_clnt.o: nfsmount_clnt.c $(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c @@ -110,8 +117,6 @@ nfsmount.x: nfsmount.o: nfs_mountversion.h nfs_mount3.h NFSMOUNTH=/usr/include/linux/nfs_mount.h -SWAPH=/usr/include/linux/swap.h -LOOPH=/usr/include/linux/loop.h nfs_mountversion.h: rm -f nfs_mountversion.h @@ -122,20 +127,15 @@ nfs_mountversion.h: echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \ fi > nfs_mountversion.h -swap.h: - rm -f swap.h - if [ -f $(SWAPH) ]; then cp $(SWAPH) .; else touch swap.h; fi - swapargs.h: sh swap.configure loop.h: - rm -f loop.h - if [ -f $(LOOPH) ]; then cp $(LOOPH) .; else touch loop.h; fi + sh mk_loop_h clean: rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff - rm -f swap.h loop.h nfs_mountversion.h + rm -f loop.h nfs_mountversion.h clobber distclean realclean: clean rm -f $(GEN_FILES) diff --git a/mount/fstab.5 b/mount/fstab.5 index 8af521b2..d343538d 100644 --- a/mount/fstab.5 +++ b/mount/fstab.5 @@ -111,7 +111,7 @@ a filesystem for mounting partitions from remote systems. a disk partition to be used for swapping. .PP If -.I vfs_fstype +.I fs_vfstype is specified as ``ignore'' the entry is ignored. This is useful to show disk partitions which are currently unused. diff --git a/mount/fstab.c b/mount/fstab.c index 6a2adc65..a67316ee 100644 --- a/mount/fstab.c +++ b/mount/fstab.c @@ -1,9 +1,9 @@ #include -#include #include #include #include #include +#include "mntent.h" #include "fstab.h" #include "sundries.h" /* for xmalloc() etc */ @@ -88,30 +88,28 @@ fstab_head() { } static void -read_mntentchn(FILE *fp, const char *fnam, struct mntentchn *mc0) { - struct mntentchn *mc = mc0; - struct mntent *mnt; - - while (!feof(fp) && !ferror(fp)) { - if ((mnt = getmntent (fp)) != NULL /* ignore blank lines */ - && *mnt->mnt_fsname != '#' /* and comment lines */ - && !streq (mnt->mnt_type, MNTTYPE_IGNORE)) { - mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); - mc->nxt->prev = mc; - mc = mc->nxt; - mc->mnt_fsname = xstrdup(mnt->mnt_fsname); - mc->mnt_dir = xstrdup(mnt->mnt_dir); - mc->mnt_type = xstrdup(mnt->mnt_type); - mc->mnt_opts = xstrdup(mnt->mnt_opts); - mc->nxt = NULL; - } - } - mc0->prev = mc; - if (ferror (fp)) { - error("warning: error reading %s: %s", fnam, strerror (errno)); - mc0->nxt = mc0->prev = NULL; - } - endmntent(fp); +read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { + struct mntentchn *mc = mc0; + struct mntent *mnt; + + while ((mnt = my_getmntent (mfp)) != NULL) { + if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) { + mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); + mc->nxt->prev = mc; + mc = mc->nxt; + mc->mnt_fsname = mnt->mnt_fsname; + mc->mnt_dir = mnt->mnt_dir; + mc->mnt_type = mnt->mnt_type; + mc->mnt_opts = mnt->mnt_opts; + mc->nxt = NULL; + } + } + mc0->prev = mc; + if (ferror (mfp->mntent_fp)) { + error("warning: error reading %s: %s", fnam, strerror (errno)); + mc0->nxt = mc0->prev = NULL; + } + my_endmntent(mfp); } /* @@ -121,7 +119,7 @@ read_mntentchn(FILE *fp, const char *fnam, struct mntentchn *mc0) { */ static void read_mounttable() { - FILE *fp = NULL; + mntFILE *mfp; const char *fnam; struct mntentchn *mc = &mounttable; @@ -129,10 +127,12 @@ read_mounttable() { mc->nxt = mc->prev = NULL; fnam = MOUNTED; - if ((fp = setmntent (fnam, "r")) == NULL) { + mfp = my_setmntent (fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; fnam = PROC_MOUNTS; - if ((fp = setmntent (fnam, "r")) == NULL) { + mfp = my_setmntent (fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { error("warning: can't open %s: %s", MOUNTED, strerror (errsv)); return; } @@ -140,12 +140,12 @@ read_mounttable() { printf ("mount: could not open %s - using %s instead\n", MOUNTED, PROC_MOUNTS); } - read_mntentchn(fp, fnam, mc); + read_mntentchn(mfp, fnam, mc); } static void read_fstab() { - FILE *fp = NULL; + mntFILE *mfp = NULL; const char *fnam; struct mntentchn *mc = &fstab; @@ -153,11 +153,12 @@ read_fstab() { mc->nxt = mc->prev = NULL; fnam = _PATH_FSTAB; - if ((fp = setmntent (fnam, "r")) == NULL) { + mfp = my_setmntent (fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { error("warning: can't open %s: %s", _PATH_FSTAB, strerror (errno)); return; } - read_mntentchn(fp, fnam, mc); + read_mntentchn(mfp, fnam, mc); } @@ -173,6 +174,24 @@ getmntfile (const char *name) { return mc; } +/* + * Given the name NAME, and the place MCPREV we found it last time, + * try to find more occurrences. + */ +struct mntentchn * +getmntfilesbackward (const char *name, struct mntentchn *mcprev) { + struct mntentchn *mc, *mh; + + mh = mtab_head(); + if (!mcprev) + mcprev = mh; + for (mc = mcprev->prev; mc && mc != mh; mc = mc->prev) + if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name))) + return mc; + + return NULL; +} + /* Given the name FILE, try to find the option "loop=FILE" in mtab. */ struct mntentchn * getmntoptfile (const char *file) @@ -222,13 +241,41 @@ getfsspec (const char *spec) return mc; } -/* Updating mtab ----------------------------------------------*/ +/* Find the uuid UUID in fstab. */ +struct mntentchn * +getfsuuidspec (const char *uuid) +{ + struct mntentchn *mc; + + for (mc = fstab_head()->nxt; mc; mc = mc->nxt) + if (strncmp (mc->mnt_fsname, "UUID=", 5) == 0 + && streq(mc->mnt_fsname + 5, uuid)) + break; + + return mc; +} -/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */ -static int lock = -1; +/* Find the label LABEL in fstab. */ +struct mntentchn * +getfsvolspec (const char *label) +{ + struct mntentchn *mc; + + for (mc = fstab_head()->nxt; mc; mc = mc->nxt) + if (strncmp (mc->mnt_fsname, "LABEL=", 6) == 0 + && streq(mc->mnt_fsname + 6, label)) + break; + + return mc; +} + +/* Updating mtab ----------------------------------------------*/ /* Flag for already existing lock file. */ -static int old_lockfile = 1; +static int we_created_lockfile = 0; + +/* Flag to indicate that signals have been set up. */ +static int signals_have_been_setup = 0; /* Ensure that the lock is released if we are interrupted. */ static void @@ -241,69 +288,122 @@ setlkw_timeout (int sig) { /* nothing, fcntl will fail anyway */ } -/* Create the lock file. The lock file will be removed if we catch a signal - or when we exit. The value of lock is tested to remove the race. */ +/* Create the lock file. + The lock file will be removed if we catch a signal or when we exit. */ +/* The old code here used flock on a lock file /etc/mtab~ and deleted + this lock file afterwards. However, as rgooch remarks, that has a + race: a second mount may be waiting on the lock and proceed as + soon as the lock file is deleted by the first mount, and immediately + afterwards a third mount comes, creates a new /etc/mtab~, applies + flock to that, and also proceeds, so that the second and third mount + now both are scribbling in /etc/mtab. + The new code uses a link() instead of a creat(), where we proceed + only if it was us that created the lock, and hence we always have + to delete the lock afterwards. Now the use of flock() is in principle + superfluous, but avoids an arbitrary sleep(). */ + +/* Where does the link point to? Obvious choices are mtab and mtab~~. + Maybe the latter is preferable. */ +#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "~" + void lock_mtab (void) { - int sig = 0; - struct sigaction sa; - struct flock flock; - - /* If this is the first time, ensure that the lock will be removed. */ - if (lock < 0) { - struct stat st; - sa.sa_handler = handler; - sa.sa_flags = 0; - sigfillset (&sa.sa_mask); - - while (sigismember (&sa.sa_mask, ++sig) != -1 && sig != SIGCHLD) { - if (sig == SIGALRM) - sa.sa_handler = setlkw_timeout; - else - sa.sa_handler = handler; - sigaction (sig, &sa, (struct sigaction *) 0); - } + int tries = 3; - /* This stat is performed so we know when not to be overly eager - when cleaning up after signals. The window between stat and - open is not significant. */ - if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT) - old_lockfile = 0; - - lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0); - if (lock < 0) { - die (EX_FILEIO, "can't create lock file %s: %s " - "(use -n flag to override)", - MOUNTED_LOCK, strerror (errno)); - } + if (!signals_have_been_setup) { + int sig = 0; + struct sigaction sa; - flock.l_type = F_WRLCK; - flock.l_whence = SEEK_SET; - flock.l_start = 0; - flock.l_len = 0; - - alarm(LOCK_BUSY); - if (fcntl (lock, F_SETLKW, &flock) < 0) { - close (lock); - /* The file should not be removed */ - lock = -1; - die (EX_FILEIO, "can't lock lock file %s: %s", - MOUNTED_LOCK, - errno == EINTR ? "timed out" : strerror (errno)); - } - /* We have now access to the lock, and it can always be removed */ - old_lockfile = 0; - } + sa.sa_handler = handler; + sa.sa_flags = 0; + sigfillset (&sa.sa_mask); + + while (sigismember (&sa.sa_mask, ++sig) != -1 + && sig != SIGCHLD) { + if (sig == SIGALRM) + sa.sa_handler = setlkw_timeout; + else + sa.sa_handler = handler; + sigaction (sig, &sa, (struct sigaction *) 0); + } + signals_have_been_setup = 1; + } + + /* Repeat until it was us who made the link */ + while (!we_created_lockfile) { + struct flock flock; + int errsv, fd, i, j; + + i = open (MOUNTLOCK_LINKTARGET, O_WRONLY|O_CREAT, 0); + if (i < 0) { + /* MOUNTLOCK_LINKTARGET does not exist (as a file) + and we cannot create it. Read-only filesystem? + Too many files open in the system? Filesystem full? */ + die (EX_FILEIO, "can't create lock file %s: %s " + "(use -n flag to override)", + MOUNTLOCK_LINKTARGET, strerror (errno)); + } + close(i); + + j = link(MOUNTLOCK_LINKTARGET, MOUNTED_LOCK); + errsv = errno; + + (void) unlink(MOUNTLOCK_LINKTARGET); + + if (j < 0 && errsv != EEXIST) { + die (EX_FILEIO, "can't link lock file %s: %s " + "(use -n flag to override)", + MOUNTED_LOCK, strerror (errsv)); + } + + fd = open (MOUNTED_LOCK, O_WRONLY); + + if (fd < 0) { + /* Strange... Maybe the file was just deleted? */ + if (errno == ENOENT && tries-- > 0) + continue; + die (EX_FILEIO, "can't open lock file %s: %s " + "(use -n flag to override)", + MOUNTED_LOCK, strerror (errno)); + } + + flock.l_type = F_WRLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + + if (j == 0) { + /* We made the link. Now claim the lock. */ + if (fcntl (fd, F_SETLK, &flock) == -1) { + if (verbose) + printf("Can't lock lock file %s: %s\n", + MOUNTED_LOCK, strerror (errno)); + /* proceed anyway */ + } + we_created_lockfile = 1; + } else { + /* Someone else made the link. Wait. */ + alarm(LOCK_TIMEOUT); + if (fcntl (fd, F_SETLKW, &flock) == -1) { + die (EX_FILEIO, "can't lock lock file %s: %s", + MOUNTED_LOCK, (errno == EINTR) ? + "timed out" : strerror (errno)); + } + alarm(0); + /* Maybe limit the number of iterations? */ + } + + close(fd); + } } /* Remove lock file. */ void unlock_mtab (void) { - if (lock != -1) { - close (lock); - if (!old_lockfile) - unlink (MOUNTED_LOCK); - } + if (we_created_lockfile) { + unlink (MOUNTED_LOCK); + we_created_lockfile = 0; + } } /* @@ -322,27 +422,32 @@ update_mtab (const char *dir, struct mntent *instead) { struct mntent *next; struct mntent remnt; int added = 0; - FILE *fp, *ftmp; + mntFILE *mfp, *mftmp; if (mtab_does_not_exist() || mtab_is_a_symlink()) return; lock_mtab(); - if ((fp = setmntent(MOUNTED, "r")) == NULL) { + mfp = my_setmntent(MOUNTED, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { error ("cannot open %s (%s) - mtab not updated", MOUNTED, strerror (errno)); goto leave; } - if ((ftmp = setmntent (MOUNTED_TEMP, "w")) == NULL) { + mftmp = my_setmntent (MOUNTED_TEMP, "w"); + if (mftmp == NULL || mfp->mntent_fp == NULL) { error ("can't open %s (%s) - mtab not updated", MOUNTED_TEMP, strerror (errno)); goto leave; } - while ((mnt = getmntent (fp))) { - if (streq (mnt->mnt_dir, dir)) { + while ((mnt = my_getmntent (mfp))) { + if (streq (mnt->mnt_dir, dir) + /* Matthew Wilcox */ + || (instead && instead->mnt_fsname && + (streq (mnt->mnt_fsname, instead->mnt_fsname)))) { added++; if (instead) { /* a remount */ remnt = *instead; @@ -362,19 +467,19 @@ update_mtab (const char *dir, struct mntent *instead) { next = NULL; } else next = mnt; - if (next && addmntent(ftmp, next) == 1) + if (next && my_addmntent(mftmp, next) == 1) die (EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror (errno)); } - if (instead && !added && addmntent(ftmp, instead) == 1) + if (instead && !added && my_addmntent(mftmp, instead) == 1) die (EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror (errno)); - endmntent (fp); - if (fchmod (fileno (ftmp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) + my_endmntent (mfp); + if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) fprintf(stderr, "error changing mode of %s: %s\n", MOUNTED_TEMP, strerror (errno)); - endmntent (ftmp); + my_endmntent (mftmp); if (rename (MOUNTED_TEMP, MOUNTED) < 0) fprintf(stderr, "can't rename %s to %s: %s\n", MOUNTED_TEMP, MOUNTED, diff --git a/mount/fstab.h b/mount/fstab.h index f22f2e7c..e0b3895c 100644 --- a/mount/fstab.h +++ b/mount/fstab.h @@ -1,7 +1,7 @@ #define _PATH_FSTAB "/etc/fstab" #define MOUNTED_LOCK "/etc/mtab~" #define MOUNTED_TEMP "/etc/mtab.tmp" -#define LOCK_BUSY 10 +#define LOCK_TIMEOUT 10 int mtab_is_writable(void); int mtab_does_not_exist(void); @@ -18,10 +18,13 @@ struct mntentchn { struct mntentchn *mtab_head (void); struct mntentchn *getmntfile (const char *name); struct mntentchn *getmntoptfile (const char *file); +struct mntentchn *getmntfilesbackward (const char *file, struct mntentchn *mc); struct mntentchn *fstab_head (void); struct mntentchn *getfsfile (const char *file); struct mntentchn *getfsspec (const char *spec); +struct mntentchn *getfsuuidspec (const char *uuid); +struct mntentchn *getfsvolspec (const char *label); #include void lock_mtab (void); diff --git a/mount/getusername.c b/mount/getusername.c new file mode 100644 index 00000000..9835768c --- /dev/null +++ b/mount/getusername.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include "getusername.h" + +char * +getusername() { + char *user = 0; + struct passwd *pw = getpwuid(getuid()); + + if (pw) + user = pw->pw_name; + return user; +} diff --git a/mount/getusername.h b/mount/getusername.h new file mode 100644 index 00000000..808ac9b8 --- /dev/null +++ b/mount/getusername.h @@ -0,0 +1 @@ +extern char *getusername(void); diff --git a/mount/linux_fs.h b/mount/linux_fs.h index 4e73c3b0..bdc548c2 100644 --- a/mount/linux_fs.h +++ b/mount/linux_fs.h @@ -4,7 +4,13 @@ in case no filesystem type was given. */ #ifndef BLKGETSIZE +#ifndef _IO +/* pre-1.3.45 */ #define BLKGETSIZE 0x1260 /* return device size */ +#else +/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ +#define BLKGETSIZE _IO(0x12,96) +#endif #endif #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ @@ -43,8 +49,11 @@ struct ext_super_block { #define EXT2_PRE_02B_MAGIC 0xEF51 #define EXT2_SUPER_MAGIC 0xEF53 struct ext2_super_block { - u_char s_dummy[56]; + u_char s_dummy1[56]; u_char s_magic[2]; + u_char s_dummy2[46]; + u_char s_uuid[16]; + u_char s_volume_name[16]; }; #define ext2magic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8)) @@ -57,3 +66,13 @@ struct xiafs_super_block { #define xiafsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \ (((uint) s.s_magic[2]) << 16) + \ (((uint) s.s_magic[3]) << 24)) + +/* From jj@sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */ +#define UFS_SUPER_MAGIC 0x00011954 +struct ufs_super_block { + u_char s_dummy[0x55c]; + u_char s_magic[4]; +}; +#define ufsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \ + (((uint) s.s_magic[2]) << 16) + \ + (((uint) s.s_magic[3]) << 24)) diff --git a/mount/losetup.c b/mount/losetup.c index 8f9dbe52..8a75a9ae 100644 --- a/mount/losetup.c +++ b/mount/losetup.c @@ -202,12 +202,12 @@ int main(int argc, char **argv) if ((delete && (argc != optind+1 || encryption || offset)) || (!delete && (argc < optind+1 || argc > optind+2))) usage(); - if (argc == optind+1) + if (argc == optind+1) { if (delete) del_loop(argv[optind]); else show_loop(argv[optind]); - else { + } else { if (offset && sscanf(offset,"%d",&off) != 1) usage(); set_loop(argv[optind],argv[optind+1],off,encryption,&ro); diff --git a/mount/mk_loop_h b/mount/mk_loop_h index 9351b57e..0f8a1a61 100644 --- a/mount/mk_loop_h +++ b/mount/mk_loop_h @@ -8,11 +8,12 @@ rm -f loop.h # Since 1.3.79 there is an include file # that defines __kernel_dev_t. # (The file itself appeared in 1.3.78, but there it defined __dev_t.) -# If it exists, we use it. Otherwise we guess that __kernel_dev_t +# If it exists, we use it, or, rather, which +# avoids namespace pollution. Otherwise we guess that __kernel_dev_t # is an unsigned short (which is true on i386, but false on alpha). -if [ -f /usr/include/asm/posix_types.h ]; then - echo '#include ' >> loop.h +if [ -f /usr/include/linux/posix_types.h ]; then + echo '#include ' >> loop.h echo '#define dev_t __kernel_dev_t' >> loop.h else echo '#define dev_t unsigned short' >> loop.h diff --git a/mount/mntent.c b/mount/mntent.c new file mode 100644 index 00000000..0be20e8c --- /dev/null +++ b/mount/mntent.c @@ -0,0 +1,214 @@ +/* Private version of the libc *mntent() routines. */ +/* Note slightly different prototypes. */ + +#include +#include /* for index */ +#include /* for isdigit */ +#include "mntent.h" +#include "sundries.h" /* for xmalloc */ + +/* Unfortunately the classical Unix /etc/mtab and /etc/fstab + do not handle directory names containing spaces. + Here we mangle them, replacing a space by \040. + What do other Unices do? */ + +static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; + +static char * +mangle(unsigned char *s) { + char *ss, *sp; + int n; + + n = strlen(s); + ss = sp = xmalloc(4*n+1); + while(1) { + for (n = 0; n < sizeof(need_escaping); n++) { + if (*s == need_escaping[n]) { + *sp++ = '\\'; + *sp++ = '0' + ((*s & 0300) >> 6); + *sp++ = '0' + ((*s & 070) >> 3); + *sp++ = '0' + (*s & 07); + goto next; + } + } + *sp++ = *s; + if (*s == 0) + break; + next: + s++; + } + return ss; +} + +static int +is_space_or_tab (char c) { + return (c == ' ' || c == '\t'); +} + +static char * +skip_spaces(char *s) { + while (is_space_or_tab(*s)) + s++; + return s; +} + +static char * +skip_nonspaces(char *s) { + while (*s && !is_space_or_tab(*s)) + s++; + return s; +} + +#define isoctal(a) (((a) & ~7) == '0') + +/* returns malloced pointer - no more strdup required */ +static char * +unmangle(char *s) { + char *ret, *ss, *sp; + + ss = skip_nonspaces(s); + ret = sp = xmalloc(ss-s+1); + while(s != ss) { + if (*s == '\\' && isoctal(s[1]) && isoctal(s[2]) && isoctal(s[3])) { + *sp++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7); + s += 4; + } else + *sp++ = *s++; + } + *sp = 0; + return ret; +} + +/* + * fstat'ing the file and allocating a buffer holding all of it + * may be a bad idea: if the file is /proc/mounttab, the stat + * returns 0. + * (On the other hand, mangling and unmangling is meaningless + * for /proc/mounttab.) + */ + +mntFILE * +my_setmntent (const char *file, char *mode) { + mntFILE *mfp = xmalloc(sizeof(*mfp)); + + mfp->mntent_fp = fopen (file, mode); + mfp->mntent_file = xstrdup(file); + mfp->mntent_errs = (mfp->mntent_fp == NULL); + mfp->mntent_softerrs = 0; + mfp->mntent_lineno = 0; + return mfp; +} + +void +my_endmntent (mntFILE *mfp) { + if (mfp) { + if (mfp->mntent_fp) + fclose(mfp->mntent_fp); + if (mfp->mntent_file) + free(mfp->mntent_file); + free(mfp); + } +} + + +int +my_addmntent (mntFILE *mfp, struct mntent *mnt) { + char *m1, *m2, *m3, *m4; + int res; + + if (fseek (mfp->mntent_fp, 0, SEEK_END)) + return 1; /* failure */ + + m1 = mangle(mnt->mnt_fsname); + m2 = mangle(mnt->mnt_dir); + m3 = mangle(mnt->mnt_type); + m4 = mangle(mnt->mnt_opts); + + res = ((fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n", + m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno) + < 0) ? 1 : 0); + + free(m1); + free(m2); + free(m3); + free(m4); + return res; +} + +/* Read the next entry from the file fp. Stop reading at an incorrect entry. */ +struct mntent * +my_getmntent (mntFILE *mfp) { + static char buf[4096]; + static struct mntent me; + char *s; + + again: + if (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX) + return NULL; + + /* read the next non-blank non-comment line */ + do { + if (fgets (buf, sizeof(buf), mfp->mntent_fp) == NULL) + return NULL; + + mfp->mntent_lineno++; + s = index (buf, '\n'); + if (s == NULL) { + /* Missing final newline? Otherwise extremely */ + /* long line - assume file was corrupted */ + if (feof(mfp->mntent_fp)) { + fprintf(stderr, "[mntent]: warning: no final " + "newline at the end of %s\n", + mfp->mntent_file); + s = index (buf, 0); + } else { + mfp->mntent_errs = 1; + goto err; + } + } + *s = 0; + s = skip_spaces(buf); + } while (*s == '\0' || *s == '#'); + + me.mnt_fsname = unmangle(s); + s = skip_nonspaces(s); + s = skip_spaces(s); + me.mnt_dir = unmangle(s); + s = skip_nonspaces(s); + s = skip_spaces(s); + me.mnt_type = unmangle(s); + s = skip_nonspaces(s); + s = skip_spaces(s); + me.mnt_opts = unmangle(s); + s = skip_nonspaces(s); + s = skip_spaces(s); + + if(isdigit(*s)) { + me.mnt_freq = atoi(s); + while(isdigit(*s)) s++; + } else + me.mnt_freq = 0; + if(*s && !is_space_or_tab(*s)) + goto err; + + s = skip_spaces(s); + if(isdigit(*s)) { + me.mnt_passno = atoi(s); + while(isdigit(*s)) s++; + } else + me.mnt_passno = 0; + if(*s && !is_space_or_tab(*s)) + goto err; + + /* allow more stuff, e.g. comments, on this line */ + + return &me; + + err: + mfp->mntent_softerrs++; + fprintf(stderr, "[mntent]: line %d in %s is bad%s\n", + mfp->mntent_lineno, mfp->mntent_file, + (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX) ? + "; rest of file ignored" : ""); + goto again; +} diff --git a/mount/mntent.h b/mount/mntent.h new file mode 100644 index 00000000..9b46ba08 --- /dev/null +++ b/mount/mntent.h @@ -0,0 +1,16 @@ +#include /* for struct mntent */ + +#define ERR_MAX 5 + +typedef struct mntFILEstruct { + FILE *mntent_fp; + char *mntent_file; + int mntent_lineno; + int mntent_errs; + int mntent_softerrs; +} mntFILE; + +mntFILE *my_setmntent (const char *file, char *mode); +void my_endmntent (mntFILE *mfp); +int my_addmntent (mntFILE *mfp, struct mntent *mnt); +struct mntent *my_getmntent (mntFILE *mfp); diff --git a/mount/mount.8 b/mount/mount.8 index 097dee00..633671b1 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -31,6 +31,8 @@ .\" 970114, aeb: xiafs and ext are dead; romfs is new .\" 970623, aeb: -F option .\" 970914, reg: -s option +.\" 981111, K.Garloff: /etc/filesystems +.\" 990111, aeb: documented /sbin/mount.smbfs .\" .TH MOUNT 8 "14 September 1997" "Linux 2.0" "Linux Programmer's Manual" .SH NAME @@ -111,6 +113,8 @@ but there are other possibilities. For example, in the case of an NFS mount, .I device may look like .IR knuth.cwi.nl:/dir . +It is possible to indicate a block special device using its +volume label or UUID (see the \-L and \-U options below). The file .I /etc/fstab @@ -163,6 +167,14 @@ or .RE For more details, see .BR fstab (5). +Only the user that mounted a filesystem can unmount it again. +If any user should be able to unmount, then use +.B users +instead of +.B user +in the +.I fstab +line. The programs .B mount @@ -265,16 +277,46 @@ Mount the file system read-only. A synonym is Mount the file system read/write. This is the default. A synonym is .BR "\-o rw" . .TP +.BI \-L " label" +Mount the partition that has the specified +.IR label . +.TP +.BI \-U " uuid" +Mount the partition that has the specified +.IR uuid . +These two options require the file +.I /proc/partitions +(present since Linux 2.1.116) to exist. +.TP .BI \-t " vfstype" The argument following the .B \-t is used to indicate the file system type. The file system types which are currently supported are listed in .IR linux/fs/filesystems.c : -.IR minix ", " ext ", " ext2 ", " xiafs ", " hpfs , -.IR msdos ", " umsdos ", " vfat , -.IR proc ", " nfs ", " iso9660 ", " smbfs ", " ncpfs , -.IR affs ", " ufs ", " romfs , +.IR minix , +.IR xiafs , +.IR ext , +.IR ext2 , +.IR msdos , +.IR umsdos , +.IR vfat , +.IR proc , +.IR autofs , +.IR devpts , +.IR nfs , +.IR iso9660 , +.IR smbfs , +.IR ncpfs , +.IR adfs , +.IR affs , +.IR coda , +.IR hfs , +.IR hpfs , +.IR ntfs , +.IR qnx4 , +.IR romfs , +.IR ufs , .IR sysv ", " xenix ", " coherent . Note that the last three are equivalent and that .I xenix @@ -288,6 +330,23 @@ and .I xiafs do not exist anymore. +For most types all the +.B mount +program has to do is issue a simple +.IR mount (2) +system call, and no detailed knowledge of the filesystem type is required. +For a few types however (like nfs, smbfs, ncpfs) ad hoc code is +necessary. The nfs ad hoc code is built in, but smbfs and ncpfs +have a separate mount program. In order to make it possible to +treat all types in a uniform way, mount will execute the program +.I /sbin/mount.TYPE +(if that exists) when called with type smb or ncp. +Since various versions of the +.I smbmount +program have different calling conventions, +.I /sbin/mount.smb +may have to be a shell script that sets up the desired call. + The type .I iso9660 is the default. If no @@ -297,9 +356,11 @@ option is given, or if the type is specified, the superblock is probed for the filesystem type .RI ( minix ", " ext ", " ext2 ", " xiafs ", " iso9660 ", " romfs are supported). -If this probe fails and -.I /proc/filesystems -exists, then all of the filesystems listed there will be tried, +If this probe fails, mount will try to read the file +.IR /etc/filesystems , +or, if that does not exist, +.IR /proc/filesystems . +All of the filesystem types listed there will be tried, except for those that are labeled "nodev" (e.g., .I proc and @@ -308,6 +369,10 @@ and Note that the .B auto type may be useful for user-mounted floppies. +Creating a file +.I /etc/filesystems +can be useful to change the probe order (e.g., to try vfat before msdos) +or if you use a kernel module autoloader. Warning: the probing uses a heuristic (the presence of appropriate `magic'), and could recognize the wrong filesystem type. @@ -381,7 +446,8 @@ binaries for architectures other than its own. .TP .B nosuid Do not allow set-user-identifier or set-group-identifier bits to take -effect. +effect. (This seems safe, but is in fact rather unsafe if you have +suidperl(1) installed.) .TP .B nouser Forbid an ordinary (i.e., non-root) user to mount the file system. @@ -1000,4 +1066,4 @@ for the .SH HISTORY A .B mount -command appeared in Version 6 AT&T UNIX. +command existed in Version 5 AT&T UNIX. diff --git a/mount/mount.c b/mount/mount.c index 19c50764..5ee247da 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -2,12 +2,6 @@ * A mount(8) for Linux 0.99. * mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp * - * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam - * J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used - * if no -t option is given. I modified his patches so that, if - * /proc/filesystems is not available, the behavior of mount is the same as - * it was previously. - * * Wed Sep 14 22:43:00 1994: Mitchum DSouza * (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for mounting * the "loop" device. @@ -15,21 +9,22 @@ * Wed Sep 14 22:55:10 1994: Sander van Malssen (svm@kozmix.hacktic.nl) * added support for remounting readonly file systems readonly. * - * Wed Feb 8 09:23:18 1995: Mike Grupenhoff added - * a probe of the superblock for the type before /proc/filesystems is - * checked. - * * Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages. * Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied. * Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes * Fri Feb 23 13:47:00 1996: aeb@cwi.nl, loop device related changes * - * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect - * * Since then, many changes - aeb. * * Wed Oct 1 23:55:28 1997: Dick Streefland * Implemented the "bg", "fg" and "retry" mount options for NFS. + * + * Tue Aug 4 15:54:31 1998: aeb@cwi.nl: + * Open fd 0,1,2 so that printf's do not clobber /etc/mtab or so. + * Mangle filenames with embedded spaces. Add ufsmagic. Add locking. + * Avoid unnecessary error messages about /proc. + * Improve support for noncanonical names in /etc/fstab. + * Add support for volume labels and UUIDs. */ #include @@ -47,22 +42,19 @@ #include "mount_constants.h" #include "sundries.h" +#include "mntent.h" #include "fstab.h" #include "lomount.h" #include "loop.h" -#include "linux_fs.h" - -#define PROC_FILESYSTEMS "/proc/filesystems" -#define SIZE(a) (sizeof(a)/sizeof(a[0])) +#include "linux_fs.h" /* for BLKGETSIZE */ +#include "mount_guess_fstype.h" +#include "mount_by_label.h" +#include "getusername.h" #define DO_PS_FIDDLING #ifdef DO_PS_FIDDLING -#define PROC_NAME "mount: " -static int argc0; -static char** argv0; -static char** envp0; -extern char** environ; +#include "setproctitle.h" #endif /* True for fake mount (-f). */ @@ -105,14 +97,15 @@ struct opt_map /* We can use the high-order 16 bits, since the mount call has MS_MGC_VAL there. */ #define MS_NOAUTO 0x80000000 -#define MS_USER 0x40000000 +#define MS_USERS 0x40000000 +#define MS_USER 0x20000000 #define MS_LOOP 0x00010000 /* Options that we keep the mount system call from seeing. */ -#define MS_NOSYS (MS_NOAUTO|MS_USER|MS_LOOP) +#define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_LOOP) /* Options that we keep from appearing in the options field in the mtab. */ -#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USER) +#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER) /* OPTIONS that we make ordinary users have by default. */ #define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV) @@ -132,6 +125,8 @@ const struct opt_map opt_map[] = { { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */ { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */ { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */ + { "users", 0, 0, MS_USERS }, /* Allow ordinary user to mount */ + { "nousers", 0, 1, MS_USERS }, /* Forbid ordinary user to mount */ { "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */ { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */ /* add new options here */ @@ -159,7 +154,7 @@ const struct opt_map opt_map[] = { { NULL, 0, 0, 0 } }; -char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption; +static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption; struct string_opt_map { char *tag; @@ -233,13 +228,12 @@ parse_opt (const char *opt, int *mask, char *extra_opts) const struct opt_map *om; for (om = opt_map; om->opt != NULL; om++) - if (streq (opt, om->opt)) - { + if (streq (opt, om->opt)) { if (om->inv) *mask &= ~om->mask; else *mask |= om->mask; - if (om->mask == MS_USER) + if (om->mask == MS_USER || om->mask == MS_USERS) *mask |= MS_SECURE; #ifdef MS_SILENT if (om->mask == MS_SILENT && om->inv) { @@ -284,8 +278,7 @@ parse_opts (char *opts, int *flags, char **extra_opts) /* Try to build a canonical options string. */ static char * -fix_opts_string (int flags, char *extra_opts) -{ +fix_opts_string (int flags, const char *extra_opts, const char *user) { const struct opt_map *om; const struct string_opt_map *m; char *new_opts; @@ -306,167 +299,14 @@ fix_opts_string (int flags, char *extra_opts) if (extra_opts && *extra_opts) { new_opts = xstrconcat3(new_opts, ",", extra_opts); } + if (user) { + new_opts = xstrconcat3(new_opts, ",user=", user); + } return new_opts; } -/* Most file system types can be recognized by a `magic' number - in the superblock. Note that the order of the tests is - significant: by coincidence a filesystem can have the - magic numbers for several file system types simultaneously. - For example, the romfs magic lives in the 1st sector; - xiafs does not touch the 1st sector and has its magic in - the 2nd sector; ext2 does not touch the first two sectors. */ - -static inline unsigned short -swapped(unsigned short a) { - return (a>>8) | (a<<8); -} - -/* - char *fstype(const char *device); - - Probes the device and attempts to determine the type of filesystem - contained within. - - Original routine by ; made into a function - for mount(8) by Mike Grupenhoff . - Read the superblock only once - aeb - Added a test for iso9660 - aeb - Added a test for high sierra (iso9660) - quinlan@bucknell.edu - Corrected the test for xiafs - aeb - Added romfs - aeb - - Currently supports: minix, ext, ext2, xiafs, iso9660, romfs -*/ -char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs" }; - static int -tested(const char *device) { - char **m; - - for (m = magic_known; m - magic_known < SIZE(magic_known); m++) - if (!strcmp(*m, device)) - return 1; - return 0; -} - -static char * -fstype(const char *device) -{ - int fd; - char *type = NULL; - union { - struct minix_super_block ms; - struct ext_super_block es; - struct ext2_super_block e2s; - } sb; - union { - struct xiafs_super_block xiasb; - char romfs_magic[8]; - } xsb; - union { - struct iso_volume_descriptor iso; - struct hs_volume_descriptor hs; - } isosb; - struct stat statbuf; - - /* opening and reading an arbitrary unknown path can have - undesired side effects - first check that `device' refers - to a block device */ - if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode)) - return 0; - - fd = open(device, O_RDONLY); - if (fd < 0) - return 0; - - if (lseek(fd, 1024, SEEK_SET) != 1024 - || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb)) - goto io_error; - - if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC - || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC - || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) - type = "ext2"; - - else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC - || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2) - type = "minix"; - - else if (extmagic(sb.es) == EXT_SUPER_MAGIC) - type = "ext"; - - if (!type) { - if (lseek(fd, 0, SEEK_SET) != 0 - || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb)) - goto io_error; - - if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC) - type = "xiafs"; - else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) - type = "romfs"; - } - - if (!type) { - if (lseek(fd, 0x8000, SEEK_SET) != 0x8000 - || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb)) - goto io_error; - - if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0 - || strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0) - type = "iso9660"; - } - - close (fd); - return(type); - -io_error: - perror(device); - close(fd); - return 0; -} - -FILE *procfs; - -static void -procclose(void) { - if (procfs) - fclose (procfs); - procfs = 0; -} - -static int -procopen(void) { - return ((procfs = fopen(PROC_FILESYSTEMS, "r")) != NULL); -} - -static char * -procnext(void) { - char line[100]; - static char fsname[50]; - - while (fgets(line, sizeof(line), procfs)) { - if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; - if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; - return fsname; - } - return 0; -} - -static int -is_in_proc(char *type) { - char *fsname; - - if (procopen()) { - while ((fsname = procnext()) != NULL) - if (!strcmp(fsname, type)) - return 1; - } - return 0; -} - -static int -already (char *spec, char *node) { +already (const char *spec, const char *node) { struct mntentchn *mc; int ret = 1; @@ -488,11 +328,12 @@ create_mtab (void) { struct mntent mnt; int flags; char *extra_opts; - FILE *fp; + mntFILE *mfp; lock_mtab(); - if ((fp = setmntent (MOUNTED, "a+")) == NULL) + mfp = my_setmntent (MOUNTED, "a+"); + if (mfp == NULL || mfp->mntent_fp == NULL) die (EX_FILEIO, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno)); @@ -502,18 +343,18 @@ create_mtab (void) { mnt.mnt_dir = "/"; mnt.mnt_fsname = canonicalize (fstab->mnt_fsname); mnt.mnt_type = fstab->mnt_type; - mnt.mnt_opts = fix_opts_string (flags, extra_opts); + mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL); mnt.mnt_freq = mnt.mnt_passno = 0; - if (addmntent (fp, &mnt) == 1) + if (my_addmntent (mfp, &mnt) == 1) die (EX_FILEIO, "mount: error writing %s: %s", MOUNTED, strerror (errno)); } - if (fchmod (fileno (fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) + if (fchmod (fileno (mfp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) if (errno != EROFS) die (EX_FILEIO, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno)); - endmntent (fp); + my_endmntent (mfp); unlock_mtab(); } @@ -522,8 +363,9 @@ create_mtab (void) { static int mountcount = 0; static int -mount5 (char *special, char *dir, char *type, int flags, void *data) { - int ret = mount (special, dir, type, 0xC0ED0000 | (flags), data); +mount5 (struct mountargs *args) { + int ret = mount (args->spec, args->node, args->type, + MS_MGC_VAL | (args->flags), args->data); if (ret == 0) mountcount++; return ret; @@ -534,46 +376,20 @@ mount5 (char *special, char *dir, char *type, int flags, void *data) { static int try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { - char *fsname; + struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts }; if (*type && strcasecmp (*type, "auto") == 0) *type = NULL; - if (!*type && !(flags & MS_REMOUNT)) { - *type = fstype(spec); - if (verbose) { - printf ("mount: you didn't specify a filesystem type for %s\n", - spec); - if (*type) - printf (" I will try type %s\n", *type); - else - printf (" I will try all types mentioned in %s\n", - PROC_FILESYSTEMS); - } - } + if (!*type && !(flags & MS_REMOUNT)) + *type = guess_fstype_from_superblock(spec); - if (*type || (flags & MS_REMOUNT)) - return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts); - - if (!procopen()) - return -1; - while ((fsname = procnext()) != NULL) { - if (tested (fsname)) - continue; - if (mount5 (spec, node, fsname, flags & ~MS_NOSYS, mount_opts) == 0) { - *type = xstrdup(fsname); - procclose(); - return 0; - } else if (errno != EINVAL) { - *type = "guess"; - procclose(); - return 1; - } + if (*type || (flags & MS_REMOUNT)) { + args.type = *type; + return mount5 (&args); } - procclose(); - *type = NULL; - return -1; + return procfsloop(mount5, &args, type); } /* @@ -584,9 +400,8 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { * background. */ static int -try_mount_one (char *spec0, char *node0, char *type0, char *opts0, - int freq, int pass, int bg) -{ +try_mount_one (const char *spec0, const char *node0, char *type0, + const char *opts0, int freq, int pass, int bg) { struct mntentchn mcn; struct mntent mnt; int mnt_err; @@ -595,7 +410,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, char *mount_opts; /* actually used on system call */ static int added_ro = 0; int loop, looptype, offset; - char *spec, *node, *type, *opts, *loopdev, *loopfile; + const char *opts; + char *spec, *node, *type, *loopdev, *loopfile; + char *user = 0; struct stat statbuf; spec = xstrdup(spec0); @@ -606,11 +423,15 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, parse_opts (xstrdup (opts), &flags, &extra_opts); /* root may allow certain types of mounts by ordinary users */ - if (suid && !(flags & MS_USER)) { - if (already (spec, node)) - die (EX_USAGE, "mount failed"); - else - die (EX_USAGE, "mount: only root can mount %s on %s", spec, node); + if (suid) { + if (!(flags & (MS_USER | MS_USERS))) { + if (already (spec, node)) + die (EX_USAGE, "mount failed"); + else + die (EX_USAGE, "mount: only root can mount %s on %s", spec, node); + } + if (flags & MS_USER) + user = getusername(); } /* quietly succeed for fstab entries that don't get mounted automatically */ @@ -661,8 +482,13 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, if (verbose) printf("mount: going to use the loop device %s\n", loopdev); offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; - if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro)) + if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro)) { + if (verbose) + printf("mount: failed setting up loop device\n"); return EX_FAIL; + } + if (verbose > 1) + printf("mount: setup loop device successfully\n"); spec = loopdev; if (loopro) flags |= MS_RDONLY; @@ -686,7 +512,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, */ if (type) #ifndef ALWAYS_STAT - if (streq (type, "smb") || streq (type, "ncp")) + if (streq (type, "smb") || streq (type, "ncp") + /* || streq (type, "smbfs") || streq (type, "ncpfs") */ + ) #else if (strlen (type) < 100) #endif @@ -701,7 +529,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, setuid(getuid()); setgid(getgid()); - oo = fix_opts_string (flags, extra_opts); + oo = fix_opts_string (flags, extra_opts, NULL); mountargs[i++] = mountprog; mountargs[i++] = spec; mountargs[i++] = node; @@ -721,7 +549,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, wait(&status); return status; } else - error("cannot fork: %s", strerror(errno)); + error("mount: cannot fork: %s", strerror(errno)); } } @@ -737,7 +565,8 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (loop ? loopfile : spec); mcn.mnt_dir = mnt.mnt_dir = canonicalize (node); mcn.mnt_type = mnt.mnt_type = type ? type : "unknown"; - mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, extra_opts); + mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, + extra_opts, user); mcn.nxt = 0; mnt.mnt_freq = freq; mnt.mnt_passno = pass; @@ -751,16 +580,20 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, if (flags & MS_REMOUNT) update_mtab (mnt.mnt_dir, &mnt); else { - FILE *fp = setmntent(MOUNTED, "a+"); - if (fp == NULL) + mntFILE *mfp; + + lock_mtab(); + mfp = my_setmntent(MOUNTED, "a+"); + if (mfp == NULL || mfp->mntent_fp == NULL) { error("mount: can't open %s: %s", MOUNTED, strerror (errno)); - else { - if ((addmntent (fp, &mnt)) == 1) + } else { + if ((my_addmntent (mfp, &mnt)) == 1) error("mount: error writing %s: %s", MOUNTED, strerror (errno)); - endmntent(fp); + my_endmntent(mfp); } + unlock_mtab(); } } @@ -794,6 +627,12 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, case EBUSY: if (flags & MS_REMOUNT) { error ("mount: %s is busy", node); + } else if (!strcmp(type, "proc") && !strcmp(node, "/proc")) { + /* heuristic: if /proc/version exists, then probably proc is mounted */ + if (stat ("/proc/version", &statbuf)) /* proc mounted? */ + error ("mount: %s is busy", node); /* no */ + else if(!all || verbose) /* yes, don't mention it */ + error ("mount: proc already mounted"); } else { error ("mount: %s already mounted or %s busy", spec, node); already (spec, node); @@ -826,7 +665,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, spec); if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) - && (fd = open(spec, O_RDONLY)) >= 0) { + && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) { if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2) error (" (aren't you trying to mount an extended partition,\n" " instead of some logical partition inside?)"); @@ -840,9 +679,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, case EIO: error ("mount: %s: can't read superblock", spec); break; case ENODEV: - if (is_in_proc(type) || !strcmp(type, "guess")) + if (is_in_procfs(type) || !strcmp(type, "guess")) error("mount: %s has wrong major or minor number", spec); - else if (procfs) { + else if (have_procfs()) { char *lowtype, *p; int u; @@ -857,9 +696,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, u++; } } - if (u && is_in_proc(lowtype)) + if (u && is_in_procfs(lowtype)) error ("mount: probably you meant %s", lowtype); - else if (!strncmp(lowtype, "iso", 3) && is_in_proc("iso9660")) + else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660")) error ("mount: maybe you meant iso9660 ?"); free(lowtype); } else @@ -893,8 +732,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, type = type0; } if (opts) { - opts = realloc(xstrdup(opts), strlen(opts)+4); - strcat(opts, ",ro"); + char *opts1 = realloc(xstrdup(opts), strlen(opts)+4); + strcat(opts1, ",ro"); + opts = opts1; } else opts = "ro"; if (type && !strcmp(type, "guess")) @@ -916,42 +756,56 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, * identified in a "ps" listing. */ static void -set_proc_name (char *spec) +set_proc_name (const char *spec) { #ifdef DO_PS_FIDDLING - int i, l; - - /* - * Move the environment so we can reuse the memory. - * (Code borrowed from sendmail.) - * WARNING: ugly assumptions on memory layout here; if this ever causes - * problems, #undef DO_PS_FIDDLING - */ - for (i = 0; envp0[i] != NULL; i++) - continue; - environ = (char **) xmalloc(sizeof(char *) * (i + 1)); - for (i = 0; envp0[i] != NULL; i++) - environ[i] = xstrdup(envp0[i]); - environ[i] = NULL; - - if (i > 0) - l = envp0[i-1] + strlen(envp0[i-1]) - argv0[0]; - else - l = argv0[argc0-1] + strlen(argv0[argc0-1]) - argv0[0]; - if (l > sizeof(PROC_NAME)) { - strcpy(argv0[0], PROC_NAME); - strncpy(argv0[0] + sizeof(PROC_NAME) - 1, spec, l - sizeof(PROC_NAME) - 1); - argv0[1] = NULL; - } + setproctitle ("mount", spec); #endif } +static char * +subst_string(const char *s, const char *sub, int sublen, const char *repl) { + char *n; + + n = (char *) xmalloc(strlen(s)-sublen+strlen(repl)+1); + strncpy (n, s, sub-s); + strcpy (n + (sub-s), repl); + strcat (n, sub+sublen); + return n; +} + +static const char * +usersubst(const char *opts) { + char *s, *w; + char id[40]; + + s = "uid=useruid"; + if (opts && (w = strstr(opts, s)) != NULL) { + sprintf(id, "uid=%d", getuid()); + opts = subst_string(opts, w, strlen(s), id); + } + s = "gid=usergid"; + if (opts && (w = strstr(opts, s)) != NULL) { + sprintf(id, "gid=%d", getgid()); + opts = subst_string(opts, w, strlen(s), id); + } + return opts; +} + + +/* + * Return 0 for success (either mounted sth or -a and NOAUTO was given) + */ static int -mount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, - int freq, int pass) -{ +mount_one (const char *spec, const char *node, char *type, const char *opts, + char *cmdlineopts, int freq, int pass) { int status; int status2; + int specset = 0; + char *nspec; + + /* Substitute values in opts, if required */ + opts = usersubst(opts); /* Merge the fstab and command line options. */ if (opts == NULL) @@ -959,6 +813,26 @@ mount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, else if (cmdlineopts != NULL) opts = xstrconcat3(opts, ",", cmdlineopts); + if (!strncmp(spec, "UUID=", 5)) { + nspec = get_spec_by_uuid(spec+5); + specset = 1; + } else if (!strncmp(spec, "LABEL=", 6)) { + nspec = get_spec_by_volume_label(spec+6); + specset = 2; + } else + nspec = 0; /* just for gcc */ + + if (specset) { + if (nspec) { + spec = nspec; + if (verbose) + printf("mount: consider mounting %s by %s\n", spec, + (specset==1) ? "UUID" : "label"); + } else if(!all) + die (EX_USAGE, "mount: no such partition found"); + /* if -a then we may be rescued by a noauto option */ + } + if (type == NULL) { if (strchr (spec, ':') != NULL) { type = "nfs"; @@ -1146,10 +1020,11 @@ static struct option longopts[] = }; const char *usage_string = "\ -usage: mount [-hV]\n\ +Usage: mount [-hV]\n\ mount -a [-nfFrsvw] [-t vfstypes]\n\ mount [-nfrsvw] [-o options] special | node\n\ mount [-nfrsvw] [-t vfstype] [-o options] special node\n\ +A special device can be indicated by -L label or -U uuid . "; static void @@ -1162,18 +1037,26 @@ usage (FILE *fp, int n) int main (int argc, char *argv[]) { - int c, result = 0; - char *options = NULL, *spec; + int c, result = 0, specseen; + char *options = NULL, *spec, *node; + char *volumelabel = NULL; + char *uuid = NULL; string_list types = NULL; struct mntentchn *mc; + int fd; + + /* People report that a mount called from init without console + writes error messages to /etc/mtab + Let us try to avoid getting fd's 0,1,2 */ + while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ; + if (fd > 2) + close(fd); #ifdef DO_PS_FIDDLING - argc0 = argc; - argv0 = argv; - envp0 = environ; + initproctitle(argc, argv); #endif - while ((c = getopt_long (argc, argv, "afFhno:rsvVwt:", longopts, NULL)) + while ((c = getopt_long (argc, argv, "afFhL:no:rsU:vVwt:", longopts, NULL)) != EOF) switch (c) { case 'a': /* mount everything in fstab */ @@ -1188,6 +1071,9 @@ main (int argc, char *argv[]) { case 'h': /* help */ usage (stdout, 0); break; + case 'L': + volumelabel = optarg; + break; case 'n': /* mount without writing in /etc/mtab */ ++nomtab; break; @@ -1207,6 +1093,9 @@ main (int argc, char *argv[]) { case 't': /* specify file system types */ types = parse_list (optarg); break; + case 'U': + uuid = optarg; + break; case 'v': /* be chatty - very chatty if repeated */ ++verbose; break; @@ -1227,7 +1116,9 @@ main (int argc, char *argv[]) { argc -= optind; argv += optind; - if (argc == 0 && !all) { + specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */ + + if (argc+specseen == 0 && !all) { if (options) usage (stderr, EX_USAGE); return print_all (types); @@ -1235,7 +1126,8 @@ main (int argc, char *argv[]) { if (getuid () != geteuid ()) { suid = 1; - if (types || options || readwrite || nomtab || all || fake || argc != 1) + if (types || options || readwrite || nomtab || all || fake || + (argc + specseen) != 1) die (EX_USAGE, "mount: only root can do that"); } @@ -1245,7 +1137,19 @@ main (int argc, char *argv[]) { create_mtab (); } - switch (argc) { + if (specseen) { + if (uuid) + spec = get_spec_by_uuid(uuid); + else + spec = get_spec_by_volume_label(volumelabel); + if (!spec) + die (EX_USAGE, "mount: no such partition found"); + if (verbose) + printf("mount: mounting %s\n", spec); + } else + spec = NULL; /* just for gcc */ + + switch (argc+specseen) { case 0: /* mount -a */ result = mount_all (types, options); @@ -1257,13 +1161,32 @@ main (int argc, char *argv[]) { /* mount [-nfrvw] [-o options] special | node */ if (types != NULL) usage (stderr, EX_USAGE); - - /* Try to find the other pathname in fstab. */ - spec = canonicalize (*argv); - if ((mc = getmntfile (spec)) == NULL && - (mc = getfsspec (spec)) == NULL && (mc = getfsfile (spec)) == NULL) - die (EX_USAGE, "mount: can't find %s in %s or %s", - spec, MOUNTED, _PATH_FSTAB); + if (specseen) { + /* We know the device. Where shall we mount it? */ + mc = (uuid ? getfsuuidspec (uuid) : getfsvolspec (volumelabel)); + if (mc == NULL) + mc = getfsspec (spec); + if (mc == NULL) + die (EX_USAGE, "mount: cannot find %s in %s", + spec, _PATH_FSTAB); + mc->mnt_fsname = spec; + } else { + /* Try to find the other pathname in fstab. */ + spec = canonicalize (*argv); + if ((mc = getfsspec (spec)) == NULL && + (mc = getfsfile (spec)) == NULL && + /* Try noncanonical name in fstab + perhaps /dev/cdrom or /dos is a symlink */ + (mc = getfsspec (*argv)) == NULL && + (mc = getfsfile (*argv)) == NULL && + /* Try mtab - maybe this was a remount */ + (mc = getmntfile (spec)) == NULL) + die (EX_USAGE, "mount: can't find %s in %s or %s", + spec, _PATH_FSTAB, MOUNTED); + /* Earlier mtab was tried first, but this would + sometimes try the wrong mount in case mtab had + the root device entry wrong. */ + } result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir), xstrdup (mc->mnt_type), mc->mnt_opts, options, 0, 0); @@ -1271,12 +1194,17 @@ main (int argc, char *argv[]) { case 2: /* mount [-nfrvw] [-t vfstype] [-o options] special node */ + if (specseen) { + /* we have spec already */ + node = argv[0]; + } else { + spec = argv[0]; + node = argv[1]; + } if (types == NULL) - result = mount_one (argv[0], argv[1], - NULL, NULL, options, 0, 0); + result = mount_one (spec, node, NULL, NULL, options, 0, 0); else if (cdr (types) == NULL) - result = mount_one (argv[0], argv[1], - car (types), NULL, options, 0, 0); + result = mount_one (spec, node, car (types), NULL, options, 0, 0); else usage (stderr, EX_USAGE); break; diff --git a/mount/mount_by_label.c b/mount/mount_by_label.c new file mode 100644 index 00000000..a48c9de1 --- /dev/null +++ b/mount/mount_by_label.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include "sundries.h" /* for xstrdup */ +#include "linux_fs.h" +#include "mount_by_label.h" + +#define PROC_PARTITIONS "/proc/partitions" +#define DEVLABELDIR "/dev" + +static FILE *procpt; + +static void +procptclose(void) { + if (procpt) + fclose (procpt); + procpt = 0; +} + +static int +procptopen(void) { + return ((procpt = fopen(PROC_PARTITIONS, "r")) != NULL); +} + +static char * +procptnext(void) { + char line[100]; + char *s; + int ma, mi, sz; + static char ptname[100]; + + while (fgets(line, sizeof(line), procpt)) { + if (sscanf (line, " %d %d %d %[^\n]\n", &ma, &mi, &sz, ptname) != 4) + continue; + + /* skip extended partitions (heuristic: size 1) */ + if (sz == 1) + continue; + + /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */ + /* heuristic: partition name ends in a digit */ + for(s = ptname; *s; s++); + if (isdigit(s[-1])) + return ptname; + } + return 0; +} + +#define UUID 1 +#define VOL 2 + +/* for now, only ext2 is supported */ +static int +has_right_label(const char *device, int n, const char *label) { + + /* start with a test for ext2, taken from mount_guess_fstype */ + /* should merge these later */ + int fd; + char *s; + struct ext2_super_block e2sb; + + fd = open(device, O_RDONLY); + if (fd < 0) + return 0; + + if (lseek(fd, 1024, SEEK_SET) != 1024 + || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb) + || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) { + close(fd); + return 0; + } + + close(fd); + + /* superblock is ext2 - now what is its label? */ + s = ((n == UUID) ? e2sb.s_uuid : e2sb.s_volume_name); + return (strncmp(s, label, 16) == 0); +} + +static char * +get_spec_by_x(int n, const char *t) { + char *pt; + char device[110]; + + if(!procptopen()) + return NULL; + while((pt = procptnext()) != NULL) { + /* Note: this is a heuristic only - there is no reason + why these devices should live in /dev. + Perhaps this directory should be specifiable by option. + One might for example have /devlabel with links to /dev + for the devices that may be accessed in this way. + (This is useful, if the cdrom on /dev/hdc must not + be accessed.) + */ + sprintf(device, "%s/%s", DEVLABELDIR, pt); + if (has_right_label(device, n, t)) { + procptclose(); + return xstrdup(device); + } + } + procptclose(); + return NULL; +} + +static u_char +fromhex(char c) { + if (isdigit(c)) + return (c - '0'); + else if (islower(c)) + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} + +char * +get_spec_by_uuid(const char *s) { + u_char uuid[16]; + int i; + + if (strlen(s) != 36 || + s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') + goto bad_uuid; + for (i=0; i<16; i++) { + if (*s == '-') s++; + if (!isxdigit(s[0]) || !isxdigit(s[1])) + goto bad_uuid; + uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1])); + s += 2; + } + return get_spec_by_x(UUID, uuid); + + bad_uuid: + die(EX_USAGE, "mount: bad UUID"); +} + +char * +get_spec_by_volume_label(const char *s) { + return get_spec_by_x(VOL, s); +} + diff --git a/mount/mount_by_label.h b/mount/mount_by_label.h new file mode 100644 index 00000000..21c2d844 --- /dev/null +++ b/mount/mount_by_label.h @@ -0,0 +1,2 @@ +char *get_spec_by_uuid(const char *uuid); +char *get_spec_by_volume_label(const char *volumelabel); diff --git a/mount/mount_constants.h b/mount/mount_constants.h index 5f033452..aeb7edfb 100644 --- a/mount/mount_constants.h +++ b/mount/mount_constants.h @@ -1,16 +1,36 @@ +#ifndef MS_RDONLY #define MS_RDONLY 1 /* Mount read-only */ +#endif +#ifndef MS_NOSUID #define MS_NOSUID 2 /* Ignore suid and sgid bits */ +#endif +#ifndef MS_NODEV #define MS_NODEV 4 /* Disallow access to device special files */ +#endif +#ifndef MS_NOEXEC #define MS_NOEXEC 8 /* Disallow program execution */ +#endif +#ifndef MS_SYNCHRONOUS #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ +#endif +#ifndef MS_REMOUNT #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#endif +#ifndef MS_MANDLOCK #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ +#endif +#ifndef MS_NOATIME #define MS_NOATIME 1024 /* Do not update access times. */ +#endif +#ifndef MS_NODIRATIME #define MS_NODIRATIME 2048 /* Do not update directory access times */ +#endif /* * Magic mount flag number. Has to be or-ed to the flag values. */ #ifndef MS_MGC_VAL #define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ #endif +#ifndef MS_MGC_MSK #define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ +#endif diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c new file mode 100644 index 00000000..b6b9e658 --- /dev/null +++ b/mount/mount_guess_fstype.c @@ -0,0 +1,252 @@ +/* + * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam + * J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used + * if no -t option is given. I modified his patches so that, if + * /proc/filesystems is not available, the behavior of mount is the same as + * it was previously. + * + * Wed Feb 8 09:23:18 1995: Mike Grupenhoff added + * a probe of the superblock for the type before /proc/filesystems is + * checked. + * + * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect + * + * Wed Nov 11 11:33:55 1998: K.Garloff@ping.de, try /etc/filesystems before + * /proc/filesystems + * + * aeb - many changes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "linux_fs.h" +#include "mount_guess_fstype.h" +#include "sundries.h" /* for xstrdup */ + +#define ETC_FILESYSTEMS "/etc/filesystems" +#define PROC_FILESYSTEMS "/proc/filesystems" + +#define SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* Most file system types can be recognized by a `magic' number + in the superblock. Note that the order of the tests is + significant: by coincidence a filesystem can have the + magic numbers for several file system types simultaneously. + For example, the romfs magic lives in the 1st sector; + xiafs does not touch the 1st sector and has its magic in + the 2nd sector; ext2 does not touch the first two sectors. */ + +static inline unsigned short +swapped(unsigned short a) { + return (a>>8) | (a<<8); +} + +/* + char *guess_fstype_from_superblock(const char *device); + + Probes the device and attempts to determine the type of filesystem + contained within. + + Original routine by ; made into a function + for mount(8) by Mike Grupenhoff . + Read the superblock only once - aeb + Added a test for iso9660 - aeb + Added a test for high sierra (iso9660) - quinlan@bucknell.edu + Corrected the test for xiafs - aeb + Added romfs - aeb + Added ufs from a patch by jj. But maybe there are several types of ufs? + + Currently supports: minix, ext, ext2, xiafs, iso9660, romfs, ufs +*/ +static char +*magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs", + "ufs" }; + +static int +tested(const char *device) { + char **m; + + for (m = magic_known; m - magic_known < SIZE(magic_known); m++) + if (!strcmp(*m, device)) + return 1; + return 0; +} + +static char * +fstype(const char *device) { + int fd; + char *type = NULL; + union { + struct minix_super_block ms; + struct ext_super_block es; + struct ext2_super_block e2s; + } sb; + union { + struct xiafs_super_block xiasb; + char romfs_magic[8]; + } xsb; + struct ufs_super_block ufssb; + union { + struct iso_volume_descriptor iso; + struct hs_volume_descriptor hs; + } isosb; + struct stat statbuf; + + /* opening and reading an arbitrary unknown path can have + undesired side effects - first check that `device' refers + to a block device */ + if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode)) + return 0; + + fd = open(device, O_RDONLY); + if (fd < 0) + return 0; + + if (lseek(fd, 1024, SEEK_SET) != 1024 + || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb)) + goto io_error; + + if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC + || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC + || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) + type = "ext2"; + + else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC + || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2) + type = "minix"; + + else if (extmagic(sb.es) == EXT_SUPER_MAGIC) + type = "ext"; + + if (!type) { + if (lseek(fd, 0, SEEK_SET) != 0 + || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb)) + goto io_error; + + if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC) + type = "xiafs"; + else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) + type = "romfs"; + } + + if (!type) { + if (lseek(fd, 8192, SEEK_SET) != 8192 + || read(fd, (char *) &ufssb, sizeof(ufssb)) != sizeof(ufssb)) + goto io_error; + + if (ufsmagic(ufssb) == UFS_SUPER_MAGIC) /* also test swapped version? */ + type = "ufs"; + } + + if (!type) { + if (lseek(fd, 0x8000, SEEK_SET) != 0x8000 + || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb)) + goto io_error; + + if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0 + || strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0) + type = "iso9660"; + } + + close (fd); + return(type); + +io_error: + perror(device); + close(fd); + return 0; +} + +char * +guess_fstype_from_superblock(const char *spec) { + char *type = fstype(spec); + if (verbose) { + printf ("mount: you didn't specify a filesystem type for %s\n", + spec); + if (type) + printf (" I will try type %s\n", type); + else + printf (" I will try all types mentioned in %s or %s\n", + ETC_FILESYSTEMS, PROC_FILESYSTEMS); + } + return type; +} + +static FILE *procfs; + +static void +procfsclose(void) { + if (procfs) + fclose (procfs); + procfs = 0; +} + +static int +procfsopen(void) { + procfs = fopen(ETC_FILESYSTEMS, "r"); + if (!procfs) + procfs = fopen(PROC_FILESYSTEMS, "r"); + return (procfs != NULL); +} + +static char * +procfsnext(void) { + char line[100]; + static char fsname[50]; + + while (fgets(line, sizeof(line), procfs)) { + if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; + if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; + return fsname; + } + return 0; +} + +int +is_in_procfs(const char *type) { + char *fsname; + + if (procfsopen()) { + while ((fsname = procfsnext()) != NULL) + if (!strcmp(fsname, type)) + return 1; + } + return 0; +} + +int +procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, + char **type) { + char *fsname; + + if (!procfsopen()) + return -1; + while ((fsname = procfsnext()) != NULL) { + if (tested (fsname)) + continue; + args->type = fsname; + if ((*mount_fn) (args) == 0) { + *type = xstrdup(fsname); + procfsclose(); + return 0; + } else if (errno != EINVAL) { + *type = "guess"; + procfsclose(); + return 1; + } + } + procfsclose(); + *type = NULL; + + return -1; +} + +int +have_procfs(void) { + return procfs != NULL; +} diff --git a/mount/mount_guess_fstype.h b/mount/mount_guess_fstype.h new file mode 100644 index 00000000..3663f74c --- /dev/null +++ b/mount/mount_guess_fstype.h @@ -0,0 +1,15 @@ +struct mountargs { + const char *spec; + const char *node; + const char *type; + int flags; + void *data; +}; + +extern int verbose; + +char *guess_fstype_from_superblock(const char *device); +int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, + char **type); +int is_in_procfs(const char *fstype); +int have_procfs(void); diff --git a/mount/nfsmount.c b/mount/nfsmount.c index fd936466..dd55d75a 100644 --- a/mount/nfsmount.c +++ b/mount/nfsmount.c @@ -151,10 +151,17 @@ int nfsmount(const char *spec, const char *node, int *flags, goto fail; } strcpy(hostdir, spec); - if ((s = (strchr(hostdir, ':')))) { + if ((s = strchr(hostdir, ':'))) { hostname = hostdir; dirname = s + 1; *s = '\0'; + /* Ignore all but first hostname in replicated mounts + until they can be fully supported. (mack@sgi.com) */ + if ((s = strchr(hostdir, ','))) { + *s = '\0'; + fprintf(stderr, "mount: warning: " + "multiple hostnames not supported\n"); + } } else { fprintf(stderr, "mount: " "directory to mount not in host:dir format\n"); @@ -272,17 +279,24 @@ int nfsmount(const char *spec, const char *node, int *flags, mountvers = val; else if (!strcmp(opt, "nfsprog")) nfsprog = val; - else if (!strcmp(opt, "nfsvers")) + else if (!strcmp(opt, "nfsvers") || + !strcmp(opt, "vers")) nfsvers = val; - else if (!strcmp(opt, "namlen")) { + else if (!strcmp(opt, "proto")) { + if (!strncmp(opteq+1, "tcp", 3)) + tcp = 1; + else if (!strncmp(opteq+1, "udp", 3)) + tcp = 0; + else + printf("Warning: Unrecognized proto= option.\n"); + } else if (!strcmp(opt, "namlen")) { #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.namlen = val; else #endif printf("Warning: Option namlen is not supported.\n"); - } - else if (!strcmp(opt, "addr")) + } else if (!strcmp(opt, "addr")) /* ignore */; else { printf("unknown nfs mount parameter: " diff --git a/mount/nfsmount_xdr.c b/mount/nfsmount_xdr.c index 6f539c24..91fbeec6 100644 --- a/mount/nfsmount_xdr.c +++ b/mount/nfsmount_xdr.c @@ -3,6 +3,9 @@ * It was generated using rpcgen. */ +#include +#include + #include "nfsmount.h" /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for @@ -40,9 +43,7 @@ /* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ bool_t -xdr_fhandle(xdrs, objp) - XDR *xdrs; - fhandle objp; +xdr_fhandle(XDR *xdrs, fhandle objp) { register long *buf; @@ -54,9 +55,7 @@ xdr_fhandle(xdrs, objp) } bool_t -xdr_fhstatus(xdrs, objp) - XDR *xdrs; - fhstatus *objp; +xdr_fhstatus(XDR *xdrs, fhstatus *objp) { register long *buf; @@ -70,14 +69,14 @@ xdr_fhstatus(xdrs, objp) return (FALSE); } break; + default: + break; } return (TRUE); } bool_t -xdr_dirpath(xdrs, objp) - XDR *xdrs; - dirpath *objp; +xdr_dirpath(XDR *xdrs, dirpath *objp) { register long *buf; @@ -89,9 +88,7 @@ xdr_dirpath(xdrs, objp) } bool_t -xdr_name(xdrs, objp) - XDR *xdrs; - name *objp; +xdr_name(XDR *xdrs, name *objp) { register long *buf; @@ -103,9 +100,7 @@ xdr_name(xdrs, objp) } bool_t -xdr_mountlist(xdrs, objp) - XDR *xdrs; - mountlist *objp; +xdr_mountlist(XDR *xdrs, mountlist *objp) { register long *buf; @@ -117,9 +112,7 @@ xdr_mountlist(xdrs, objp) } bool_t -xdr_mountbody(xdrs, objp) - XDR *xdrs; - mountbody *objp; +xdr_mountbody(XDR *xdrs, mountbody *objp) { register long *buf; @@ -137,9 +130,7 @@ xdr_mountbody(xdrs, objp) } bool_t -xdr_groups(xdrs, objp) - XDR *xdrs; - groups *objp; +xdr_groups(XDR *xdrs, groups *objp) { register long *buf; @@ -151,9 +142,7 @@ xdr_groups(xdrs, objp) } bool_t -xdr_groupnode(xdrs, objp) - XDR *xdrs; - groupnode *objp; +xdr_groupnode(XDR *xdrs, groupnode *objp) { register long *buf; @@ -168,9 +157,7 @@ xdr_groupnode(xdrs, objp) } bool_t -xdr_exports(xdrs, objp) - XDR *xdrs; - exports *objp; +xdr_exports(XDR *xdrs, exports *objp) { register long *buf; @@ -182,9 +169,7 @@ xdr_exports(xdrs, objp) } bool_t -xdr_exportnode(xdrs, objp) - XDR *xdrs; - exportnode *objp; +xdr_exportnode(XDR *xdrs, exportnode *objp) { register long *buf; @@ -202,9 +187,7 @@ xdr_exportnode(xdrs, objp) } bool_t -xdr_ppathcnf(xdrs, objp) - XDR *xdrs; - ppathcnf *objp; +xdr_ppathcnf(XDR *xdrs, ppathcnf *objp) { register long *buf; diff --git a/mount/sundries.c b/mount/sundries.c index 4506924a..d7ace1b2 100644 --- a/mount/sundries.c +++ b/mount/sundries.c @@ -29,12 +29,12 @@ xmalloc (size_t size) { void *t; if (size == 0) - return NULL; + return NULL; t = malloc (size); if (t == NULL) - die (EX_SYSERR, "not enough memory"); - + die (EX_SYSERR, "not enough memory"); + return t; } @@ -43,12 +43,12 @@ xstrdup (const char *s) { char *t; if (s == NULL) - return NULL; - + return NULL; + t = strdup (s); if (t == NULL) - die (EX_SYSERR, "not enough memory"); + die (EX_SYSERR, "not enough memory"); return t; } diff --git a/mount/swap.configure b/mount/swap.configure index a557e187..ebd67ced 100644 --- a/mount/swap.configure +++ b/mount/swap.configure @@ -1,24 +1,36 @@ # Find out whether we can include # and whether libc thinks that swapon() has two arguments. -# Of course this will fail if exists but belongs -# to a libc that is not in use at present. + +# Prepare test CC=${CC-cc} compile="$CC -o conftest conftest.c >/dev/null 2>&1" rm -f conftest conftest.c swapargs.h + +# What include files shall we try? +# Unfortunately, recent versions of swap.h use PAGE_SIZE and hence need page.h +# It is used only in mkswap, not in swapon/swapoff, so we might just pick any +# random value (like #define PAGE_SIZE 4096) instead of including page.h. SWAPH= -if [ -f /usr/include/sys/swap.h ]; then SWAPH="#include "; fi -echo $SWAPH > conftest.c +PAGEH= +if [ -f /usr/include/sys/swap.h ]; then + SWAPH="#include " + if [ -f /usr/include/asm/page.h ]; then + PAGEH="#include " + fi +fi +echo $PAGEH > conftest.c +echo $SWAPH >> conftest.c echo '#include main(){ exit(0); swapon("/dev/null", 0); }' >> conftest.c eval $compile if test -s conftest && ./conftest 2>/dev/null; then echo "#define SWAPON_HAS_TWO_ARGS" > swapargs.h + echo $PAGEH >> swapargs.h echo $SWAPH >> swapargs.h else echo > swapargs.h echo " Your libc thinks that swapon has 1 arg only. -Define SWAPON_NEEDS_TWO_ARGS in swapon.c if you want to use priorities. " 1>&2 fi rm -f conftest conftest.c diff --git a/mount/swap_constants.h b/mount/swap_constants.h new file mode 100644 index 00000000..c7e8b4c7 --- /dev/null +++ b/mount/swap_constants.h @@ -0,0 +1,15 @@ +/* + * It is too painful to get these out of + * (which again requires etc). + * These exist since Linux 1.3.2. + */ + +#ifndef SWAP_FLAG_PREFER +#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ +#endif +#ifndef SWAP_FLAG_PRIO_MASK +#define SWAP_FLAG_PRIO_MASK 0x7fff +#endif +#ifndef SWAP_FLAG_PRIO_SHIFT +#define SWAP_FLAG_PRIO_SHIFT 0 +#endif diff --git a/mount/swapon.8 b/mount/swapon.8 index 0ebb450a..74f61eea 100644 --- a/mount/swapon.8 +++ b/mount/swapon.8 @@ -74,7 +74,10 @@ Provide help Display version .TP .B \-s -Display swap usage summary by device +Display swap usage summary by device. +This option is only available if +.I /proc/swaps +exists (probably not before kernel 2.1.25). .TP .B \-a All devices marked as ``sw'' swap devices in @@ -104,6 +107,10 @@ entries in when the .B \-a flag is given. +.SH NOTE +You should not use +.B swapon +on a file with holes. .SH SEE ALSO .BR swapon "(2), " swapoff "(2), " fstab "(5), " init "(8), " mkswap (8), .BR rc "(8), " mount (8) @@ -120,8 +127,3 @@ ascii filesystem description table The .B swapon command appeared in 4.0BSD. -.SH AUTHORS -See the Linux -.BR mount (8) -man page for a complete author list. Primary contributors include Doug -Quale, H. J. Lu, Rick Sladkey, and Stephen Tweedie. diff --git a/mount/swapon.c b/mount/swapon.c index 5fdd15c5..41d1f3fc 100644 --- a/mount/swapon.c +++ b/mount/swapon.c @@ -10,7 +10,8 @@ #include #include #include -#include "swap.h" +#include +#include "swap_constants.h" #include "swapargs.h" #define streq(s, t) (strcmp ((s), (t)) == 0) @@ -18,7 +19,7 @@ #define _PATH_FSTAB "/etc/fstab" #define PROC_SWAPS "/proc/swaps" -/* #define SWAPON_NEEDS_TWO_ARGS */ +#define SWAPON_NEEDS_TWO_ARGS /* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */ int verbose = 0; @@ -77,12 +78,34 @@ static int swap (const char *special, int prio) { int status; + struct stat st; if (verbose) - printf("%s on device %s\n", program_name, special); + printf("%s on %s\n", program_name, special); if (streq (program_name, "swapon")) { + if (stat(special, &st) < 0) { + fprintf (stderr, "swapon: cannot stat %s: %s\n", special, strerror (errno)); + return -1; + } + + if ((st.st_mode & 07077) != 0) { + fprintf(stderr, "swapon: warning: %s has insecure permissions %04o, " + "0600 suggested\n", special, st.st_mode & 07777); + } + + /* test for holes by LBT */ + if (S_ISREG(st.st_mode)) { + if (st.st_blocks * 512 < st.st_size) { + fprintf(stderr, + "swapon: Skipping file %s - it appears to have holes.\n", + special); + return -1; + } + } + #ifdef SWAPON_NEEDS_TWO_ARGS + { int flags = 0; #ifdef SWAP_FLAG_PREFER @@ -94,6 +117,7 @@ swap (const char *special, int prio) } #endif status = swapon (special, flags); + } #else status = swapon (special); #endif diff --git a/mount/umount.c b/mount/umount.c index 6f28213b..ac233a70 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -18,6 +18,10 @@ * 960823: aeb - also try umount(spec) when umount(node) fails * 970307: aeb - canonise names from fstab * 970726: aeb - remount read-only in cases where umount fails + * 980810: aeb - umount2 support + * 981222: aeb - If mount point or special file occurs several times + * in mtab, try them all, with last one tried first + * - Differentiate "user" and "users" key words in fstab */ #include @@ -28,6 +32,7 @@ #include #include "mount_constants.h" #include "sundries.h" +#include "getusername.h" #include "lomount.h" #include "loop.h" #include "fstab.h" @@ -43,11 +48,33 @@ #include #endif +static int umount2(const char *path, int flags); -#ifdef notyet -/* Nonzero for force umount (-f). This needs kernel support we don't have. */ +#ifdef MNT_FORCE +/* Interesting ... it seems libc knows about MNT_FORCE and presumably + about umount2 as well -- need not do anything */ +#else /* MNT_FORCE */ + +/* Does the present kernel source know about umount2? */ +#include +#ifdef __NR_umount2 +_syscall2(int, umount2, const char *, path, int, flags); +#else /* __NR_umount2 */ +static int +umount2(const char *path, int flags) { + fprintf(stderr, "umount: compiled without support for -f\n"); + errno = ENOSYS; + return -1; +} +#endif /* __NR_umount2 */ + +/* dare not try to include -- lots of errors */ +#define MNT_FORCE 1 + +#endif /* MNT_FORCE */ + +/* Nonzero for force umount (-f). There is kernel support since 2.1.116. */ int force = 0; -#endif /* When umount fails, attempt a read-only remount (-r). */ int remount = 0; @@ -169,7 +196,7 @@ static void complain(int err, const char *dev) { on a non-fatal error. We lock/unlock around each umount. */ static int umount_one (const char *spec, const char *node, const char *type, - const char *opts) + const char *opts, struct mntentchn *mc) { int umnt_err, umnt_err2; int isroot; @@ -195,7 +222,22 @@ umount_one (const char *spec, const char *node, const char *type, umnt_err = umnt_err2 = 0; - res = umount (node); + if (force) { + /* completely untested - 2.1.116 only has some support in nfs case */ + /* probably this won't work */ + int flags = MNT_FORCE; + + res = umount2 (node, flags); + if (res == -1) { + perror("umount2"); + if (errno == ENOSYS) { + if (verbose) + printf("no umount2, trying umount...\n"); + res = umount (node); + } + } + } else + res = umount (node); if (res < 0) { umnt_err = errno; /* A device might have been mounted on a node that has since @@ -238,11 +280,9 @@ umount_one (const char *spec, const char *node, const char *type, printf ("%s umounted\n", spec); if (!nomtab && mtab_is_writable()) { - struct mntentchn *mc; /* Special stuff for loop devices */ - - if ((mc = getmntfile (spec)) || (mc = getmntfile (node))) { - char *opts; + if (mc) { + char *optl; /* old style mtab line? */ if (streq(mc->mnt_type, "loop")) @@ -250,10 +290,10 @@ umount_one (const char *spec, const char *node, const char *type, goto fail; /* new style mtab line? */ - opts = mc->mnt_opts ? xstrdup(mc->mnt_opts) : ""; - for (opts = strtok (opts, ","); opts; opts = strtok (NULL, ",")) { - if (!strncmp(opts, "loop=", 5)) { - if (del_loop(opts+5)) + optl = mc->mnt_opts ? xstrdup(mc->mnt_opts) : ""; + for (optl = strtok (optl, ","); optl; optl = strtok (NULL, ",")) { + if (!strncmp(optl, "loop=", 5)) { + if (del_loop(optl+5)) goto fail; break; } @@ -286,6 +326,28 @@ fail: return 1; } +/* + * Why this loop? + * 1. People who boot a system with a bad fstab root entry + * will get an incorrect "/dev/foo on /" in mtab. + * If later /dev/foo is actually mounted elsewhere, + * it will occur twice in mtab. + * 2. With overmounting one can get the situation that + * the same filename is used as mount point twice. + * In both cases, it is best to try the last occurrence first. + */ +static int +umount_one_bw (const char *file, struct mntentchn *mc) { + int res = 1; + + while (res && mc) { + res = umount_one(mc->mnt_fsname, mc->mnt_dir, + mc->mnt_type, mc->mnt_opts, mc); + mc = getmntfilesbackward (file, mc); + } + return res; +} + /* Unmount all filesystems of type VFSTYPES found in mtab. Since we are concurrently updating mtab after every succesful umount, we have to slurp in the entire file before we start. This isn't too bad, because @@ -302,7 +364,7 @@ umount_all (string_list types) { for (mc = hd->prev; mc != hd; mc = mc->prev) { if (matching_type (mc->mnt_type, types)) { errors |= umount_one (mc->mnt_fsname, mc->mnt_dir, - mc->mnt_type, mc->mnt_opts); + mc->mnt_type, mc->mnt_opts, mc); } } @@ -325,9 +387,9 @@ static struct option longopts[] = }; char *usage_string = "\ -usage: umount [-hV]\n\ - umount -a [-r] [-n] [-v] [-t vfstypes]\n\ - umount [-r] [-n] [-v] special | node...\n\ +Usage: umount [-hV]\n\ + umount -a [-f] [-r] [-n] [-v] [-t vfstypes]\n\ + umount [-f] [-r] [-n] [-v] special | node...\n\ "; static void @@ -350,22 +412,19 @@ main (int argc, char *argv[]) char *file; int result = 0; - while ((c = getopt_long (argc, argv, "afhnrvVt:", longopts, NULL)) != EOF) + while ((c = getopt_long (argc, argv, "afhnrt:vV", + longopts, NULL)) != EOF) switch (c) { case 'a': /* umount everything */ ++all; break; - case 'f': /* force umount (needs kernel support) */ -#if 0 + case 'f': /* force umount */ ++force; -#else - die (2, "umount: forced umount not supported yet"); -#endif break; case 'h': /* help */ usage (stdout, 0); break; - case 'n': + case 'n': /* do not write in /etc/mtab */ ++nomtab; break; case 'r': /* remount read-only if umount fails */ @@ -390,7 +449,7 @@ main (int argc, char *argv[]) if (getuid () != geteuid ()) { suid = 1; - if (all || types || nomtab) + if (all || types || nomtab || force) die (2, "umount: only root can do that"); } @@ -408,13 +467,15 @@ main (int argc, char *argv[]) if (verbose > 1) printf("Trying to umount %s\n", file); - mc = getmntfile (file); + mc = getmntfilesbackward (file, NULL); if (!mc && verbose) printf("Could not find %s in mtab\n", file); if (suid) { if (!mc) die (2, "umount: %s is not mounted (according to mtab)", file); + if (getmntfilesbackward (file, mc)) + die (2, "umount: it seems %s is mounted multiple times", file); if (!(fs = getfsspec (file)) && !(fs = getfsfile (file))) die (2, "umount: %s is not in the fstab (and you are not root)", file); @@ -424,22 +485,46 @@ main (int argc, char *argv[]) !streq (mc->mnt_dir, canonicalize (fs->mnt_dir)))) { die (2, "umount: %s mount disagrees with the fstab", file); } + + /* User mounting and unmounting is allowed only + if fstab contains the option `user' or `users' */ + /* The option `users' allows arbitrary users to mount + and unmount - this may be a security risk. */ + /* The option `user' only allows unmounting by the user + that mounted. */ + /* A convenient side effect is that the user who mounted + is visible in mtab. */ options = parse_list (fs->mnt_opts); while (options) { - if (streq (car (options), "user")) + if (streq (car (options), "user") || + streq (car (options), "users")) break; options = cdr (options); } if (!options) die (2, "umount: only root can unmount %s from %s", fs->mnt_fsname, fs->mnt_dir); + if (streq (car (options), "user")) { + char *user = getusername(); + + options = parse_list (mc->mnt_opts); + while (options) { + char *co = car (options); + if (!strncmp(co, "user=", 5)) { + if (!user || !streq(co+5,user)) + die(2, "umount: only %s can unmount %s from %s", + co+5, fs->mnt_fsname, fs->mnt_dir); + break; + } + options = cdr (options); + } + } } if (mc) - result = umount_one (xstrdup(mc->mnt_fsname), xstrdup(mc->mnt_dir), - xstrdup(mc->mnt_type), xstrdup(mc->mnt_opts)); + result = umount_one_bw (file, mc); else - result = umount_one (*argv, *argv, *argv, *argv); + result = umount_one (*argv, *argv, *argv, *argv, NULL); argv++; diff --git a/mount/version.c b/mount/version.c index 0c9363d3..790c447b 100644 --- a/mount/version.c +++ b/mount/version.c @@ -1 +1,2 @@ -char version[] = "mount-2.8"; +#include "../version.h" +char version[] = "mount-" UTIL_LINUX_VERSION; diff --git a/sys-utils/Makefile b/sys-utils/Makefile index 9085fa96..91aa32d1 100644 --- a/sys-utils/Makefile +++ b/sys-utils/Makefile @@ -11,9 +11,9 @@ include ../MCONFIG MAN1= arch.1 readprofile.1 -MAN8= ctrlaltdel.8 cytune.8 dmesg.8 \ +MAN8= ctrlaltdel.8 cytune.8 dmesg.8 hwclock.8 \ ipcrm.8 ipcs.8 kbdrate.8 ramsize.8 renice.8 \ - rootflags.8 setsid.8 swapdev.8 tunelp.8 \ + rootflags.8 setsid.8 sln.8 swapdev.8 tunelp.8 \ vidmode.8 # Where to put binaries? @@ -23,15 +23,14 @@ BIN= arch dmesg USRBIN= cytune ipcrm ipcs renice readprofile setsid tunelp -SBIN= sln ctrlaltdel kbdrate +SBIN= ctrlaltdel hwclock kbdrate -ifneq "$(CPU)" "sparc" -MAN8:= $(MAN8) hwclock.8 -SBIN:=$(SBIN) hwclock +ifeq "$(HAVE_SLN)" "no" +SBIN:=$(SBIN) sln endif ifeq "$(CPU)" "intel" -MAN8:= $(MAN8) rdev.8 +MAN8:=$(MAN8) rdev.8 USRBIN:=$(USRBIN) rdev endif @@ -49,7 +48,8 @@ sln: sln.c arch: arch.o hwclock.o: hwclock.c shhopt.h hwclock: hwclock.o shhopt.o -ctrlaltdel: ctrlaltdel.o +ctrlaltdel.o: ctrlaltdel.c $(LIB)/linux_reboot.h +ctrlaltdel: ctrlaltdel.o $(LIB)/my_reboot.o ipcrm: ipcrm.o ipcs: ipcs.o kbdrate: kbdrate.o diff --git a/sys-utils/ctrlaltdel.c b/sys-utils/ctrlaltdel.c index e5565d70..c754fd05 100644 --- a/sys-utils/ctrlaltdel.c +++ b/sys-utils/ctrlaltdel.c @@ -7,24 +7,24 @@ #include #include #include - -int reboot(int magic, int magictoo, int flag); +#include "linux_reboot.h" int main(int argc, char *argv[]) { if(geteuid()) { - fprintf(stderr, "You must be root to set the Ctrl-Alt-Del behaviour.\n"); + fprintf(stderr, + "You must be root to set the Ctrl-Alt-Del behaviour.\n"); exit(1); } if(argc == 2 && !strcmp("hard", argv[1])) { - if(reboot(0xfee1dead, 672274793, 0x89abcdef) < 0) { + if(my_reboot(LINUX_REBOOT_CMD_CAD_ON) < 0) { perror("ctrlaltdel: reboot"); exit(1); } } else if(argc == 2 && !strcmp("soft", argv[1])) { - if(reboot(0xfee1dead, 672274793, 0) < 0) { + if(my_reboot(LINUX_REBOOT_CMD_CAD_OFF) < 0) { perror("ctrlaltdel: reboot"); exit(1); } diff --git a/sys-utils/hwclock.8 b/sys-utils/hwclock.8 index ec8b0076..58f4a259 100644 --- a/sys-utils/hwclock.8 +++ b/sys-utils/hwclock.8 @@ -55,8 +55,17 @@ Set the Hardware Clock to the time given by the option. .TP .B \-\-hctosys -Set the System Time from the Hardware Clock. This is a good option to use -in one of the system startup scripts. +Set the System Time from the Hardware Clock. + +Also set the kernel's timezone value to the local timezone as indicated by +the TZ environment variable and/or /usr/lib/zoneinfo, as tzset(3) would +interpret them. EXCEPT: always set the Daylight Savings Time part of +the kernel's timezone value to 0 ("not Daylight Savings Time"). If DST +is indicated, just add an hour to the base part. + +See the discussion of timezones below. + +This is a good option to use in one of the system startup scripts. .TP .B \-\-systohc Set the Hardware Clock to the current System Time. @@ -118,11 +127,19 @@ Time. It is your choice whether to keep your clock in UTC or local time, but nothing in the clock tells which you've chosen. So this option is how you give that information to .I hwclock. -.PP -If you don't specify -.B --utc -when you should, or vice versa, both setting and querying of the -Hardware Clock will be messed up. + +In order to avoid any possible misunderstandings: all conversation +with the program +.I hwclock +is done in local time. If you have your clock in UTC +(as is common on a Unix system) then the option +.B --utc +tells +.I hwclock +to do the appropriate conversions: `hwclock \-\-show \-\-utc' +will tell you the local time, assuming the hardware clock is in UTC, +and `hwclock \-\-set \-\-date="XXX" \-\-utc' will set the +hardware clock to the UTC equivalent of the local time XXX. .TP .B \-\-directisa is meaningful only on an ISA machine. For all other machines, it has @@ -134,7 +151,7 @@ Without this option, will try to use the /dev/rtc device (which it assumes to be driven by the rtc device driver). If it is unable to open the device (for read), it will use the explicit I/O instructions anyway. -.PP + The rtc device driver was new in Linux Release 2. .TP .B \-\-test @@ -198,7 +215,42 @@ time Linux starts up, it will do so with the adjusted time from the Hardware Clock. You can also use the program .I adjtimex(8) to smoothly adjust the System Time while the system runs. - +.PP +A Linux kernel maintains a concept of a local timezone for the system. +But don't be misled -- almost nobody cares what timezone the kernel +thinks it is in. Instead, programs that care about the timezone +(perhaps because they want to display a local time for you) almost +always use a more traditional method of determining the timezone: They +use the TZ environment variable and/or the /usr/local/timezone +directory, as explained in the man page for tzset(3). However, some +programs and fringe parts of the Linux kernel such as filesystems use +the kernel timezone value. An example is the vfat filesystem. If the +kernel timezone value is wrong, the vfat filesystem will report and +set the wrong timestamps on files. +.PP +.I hwclock +sets the kernel timezone to the value indicated by TZ and/or +/usr/local/timezone when you set the System Time using the +.B \-\-hctosys +option. +.PP +A complication is that the timezone value actually consists of two +parts: 1) how far from the Standard Meridian the locality is +geographically, and 2) whether or not a Daylight Savings Time (DST) +convention is in effect in the locality at the present time. In +practice, the DST part of the timezone value is almost never used, so +if the geographical part were to be set to its correct value, the +users of the timezone value would actually compute the wrong local +time. +.PP +Therefore, +.I +hwclock +violates the definition of the kernel's timezone value and always sets +the DST part to zero. If DST is supposed to be in effect, +.I +hwclock +simply adds an hour to the geographical part. .SH How hwclock Accesses the Hardware Clock .PP @@ -302,7 +354,11 @@ Another 24 hours goes by and you issue another does the same thing: subtracts 2 seconds and updates the adjtime file with the current time as the last time the clock was adjusted. .PP -Every time you calibrate (set) the clock, +Every time you calibrate (set) the clock (using +.I --set +or +.I --systohc +), .I hwclock recalculates the systematic drift rate based on how long it has been since the last calibration, how long it has been since the last @@ -324,12 +380,12 @@ just before the at system startup time, and maybe periodically while the system is running via cron. .PP -The format of the adjtime file is: +The format of the adjtime file is, in ASCII: .PP -Line 1: 3 numbers: 1) systematic drift rate in seconds per day, -floating point decimal; 2) Resulting number of seconds since 1969 UTC -of most recent adjustment or calibration, decimal integer; 3) zero -(for compatibility with +Line 1: 3 numbers, separated by blanks: 1) systematic drift rate in +seconds per day, floating point decimal; 2) Resulting number of +seconds since 1969 UTC of most recent adjustment or calibration, +decimal integer; 3) zero (for compatibility with .I clock ). .PP @@ -341,11 +397,51 @@ You can use an adjtime file that was previously used with the program with .I hwclock. + +.SH Automatic Hardware Clock Synchronization By the Kernel + +You should be aware of another way that the Hardware Clock is kept +synchronized in some systems. The Linux kernel has a mode wherein it +copies the System Time to the Hardware Clock every 11 minutes. +This is a good mode to use when you are using something sophisticated +like ntp to keep your System Time synchronized. (ntp is a way to keep +your System Time synchronized either to a time server somewhere on the +network or to a radio clock hooked up to your system. See RFC 1305). + +This mode (we'll call it "11 minute mode") is off until something +turns it on. The ntp daemon xntpd is one thing that turns it on. You +can turn it off by running anything, including +.I hwclock --hctosys +, that sets the System Time the old fashioned way. + +To see if it is on or +off, use the command +.I adjtimex --print +and look at the value of "status". If the "64" bit of this number +(expressed in binary) equal to 0, 11 minute mode is on. Otherwise, it +is off. + +If your system runs with 11 minute mode on, don't use +.I hwclock --adjust +or +.I hwclock --hctosys . +You'll just make a mess. It is acceptable to use a +.I hwclock --hctosys +at startup time to get a reasonable System Time until your system is +able to set the System Time from the external source and start 11 +minute mode. + + +.SH ENVIRONMENT VARIABLES +.I TZ + .SH FILES .I /etc/adjtime +.I /usr/lib/zoneinfo/ .SH SEE ALSO -adjtimex(8), date(1), gettimeofday(2), settimeofday(2), crontab(1) +adjtimex(8), date(1), gettimeofday(2), settimeofday(2), crontab(1), +tzset(3) .SH AUTHORS Written By Bryan Henderson, September 1996 (bryanh@giraffe-data.com), @@ -353,5 +449,3 @@ based on work done on the .I clock program by Charles Hedrick, Rob Hooft, and Harald Koenig. See the source code for complete history and credits. - - diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c index 643ccda5..02302da2 100644 --- a/sys-utils/hwclock.c +++ b/sys-utils/hwclock.c @@ -106,12 +106,14 @@ #include #include #include -#include +#ifdef __i386__ +#include /* for inb, outb */ +#endif #include #include "../version.h" #define MYNAME "hwclock" -#define VERSION "2.2" +#define VERSION "2.4" #define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); @@ -190,7 +192,6 @@ bool interrupts_enabled; need to be turned back on. */ - #include /* Check if the /dev/rtc interface is available in this version of the system headers. 131072 is linux 2.0.0. Might need to make @@ -658,17 +659,27 @@ synchronize_to_clock_tick(enum clock_access_method clock_access, -static time_t -mktime_tz(struct tm tm, const bool universal) { +static void +mktime_tz(struct tm tm, const bool universal, + bool *valid_p, time_t *systime_p) { /*----------------------------------------------------------------------------- Convert a time in broken down format (hours, minutes, etc.) into standard - unix time (seconds into epoch). + unix time (seconds into epoch). Return it as *systime_p. The broken down time is argument . This broken down time is either in local time zone or UTC, depending on value of logical argument "universal". True means it is in UTC. + + If the argument contains values that do not constitute a valid time, + and mktime() recognizes this, return *valid_p == false and + *systime_p undefined. However, mktime() sometimes goes ahead and + computes a fictional time "as if" the input values were valid, + e.g. if they indicate the 31st day of April, mktime() may compute + the time of May 1. In such a case, we return the same fictional + value mktime() does as *systime_p and return *valid_p == true. + -----------------------------------------------------------------------------*/ - time_t systime; /* our eventual return value */ + time_t mktime_result; /* The value returned by our mktime() call */ char *zone; /* Local time zone name */ /* We use the C library function mktime(), but since it only works on @@ -686,23 +697,31 @@ mktime_tz(struct tm tm, const bool universal) { */ tzset(); } - systime = mktime(&tm); - if (systime == -1) { - /* We don't expect this to happen. Consider this a crash */ - fprintf(stderr, "mktime() failed unexpectedly (rc -1). Aborting.\n"); - exit(2); + mktime_result = mktime(&tm); + if (mktime_result == -1) { + /* This apparently (not specified in mktime() documentation) means + the 'tm' structure does not contain valid values (however, not + containing valid values does _not_ imply mktime() returns -1). + */ + *valid_p = FALSE; + *systime_p = 0; + if (debug) + printf("Invalid values in hardware clock: " + "%2d/%.2d/%.2d %.2d:%.2d:%.2d\n", + tm.tm_year, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec + ); + } else { + *valid_p = TRUE; + *systime_p = mktime_result; + if (debug) + printf("Hw clock time : %.2d:%.2d:%.2d = %d seconds since 1969\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, (int) *systime_p); } - /* now put back the original zone. */ if (zone) setenv("TZ", zone, TRUE); else unsetenv("TZ"); tzset(); - - if (debug) - printf("Hw clock time : %.2d:%.2d:%.2d = %d seconds since 1969\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, (int) systime); - - return(systime); } @@ -837,32 +856,28 @@ read_hardware_clock_isa(struct tm *tm) { tm->tm_mday = hclock_read_bcd(7); tm->tm_mon = hclock_read_bcd(8) - 1; tm->tm_year = hclock_read_bcd(9); - if (hclock_read_bcd(50) == 0) { - /* I suppose Linux could run on an old machine that doesn't implement - the Byte 50 century value, and that if it does, that machine puts - zero in Byte 50. If so, this could could be useful, in that it - makes values 70-99 -> 1970-1999 and 00-69 -> 2000-2069. - */ - if (hclock_read_bcd(9) >= 70) tm->tm_year = hclock_read_bcd(9); - else tm->tm_year = hclock_read_bcd(9) + 100; - } else { - tm->tm_year = hclock_read_bcd(50) * 100 + hclock_read_bcd(9) - 1900; - /* Note: Byte 50 contains centuries since A.D. Byte 9 contains - years since beginning of century. tm_year contains years - since 1900. At least we _assume_ that's what tm_year - contains. It is documented only as "year", and it could - conceivably be years since the beginning of the current - century. If so, this code won't work after 1999. - */ - } - /* Unless the clock changed while we were reading, consider this - a good clock read . + /* We don't use the century byte (Byte 50) of the Hardware Clock. + Here's why: On older machines, it isn't defined. In at least + one reported case, a machine puts some arbitrary value in that + byte. Furthermore, the Linux standard time data structure doesn't + allow for times beyond about 2037 and no Linux systems were + running before 1937. Therefore, all the century byte could tell + us is that the clock is wrong or this whole program is obsolete! + + So we just say if the year of century is less than 37, it's the + 21st century, otherwise it's the 20th. */ - if (tm->tm_sec == hclock_read_bcd (0)) got_time = TRUE; - /* Yes, in theory we could have been running for 60 seconds and - the above test wouldn't work! - */ + + if (hclock_read_bcd(9) >= 37) tm->tm_year = hclock_read_bcd(9); + else tm->tm_year = hclock_read_bcd(9) + 100; } + /* Unless the clock changed while we were reading, consider this + a good clock read . + */ + if (tm->tm_sec == hclock_read_bcd (0)) got_time = TRUE; + /* Yes, in theory we could have been running for 60 seconds and + the above test wouldn't work! + */ } tm->tm_isdst = -1; /* don't know whether it's daylight */ } @@ -870,21 +885,25 @@ read_hardware_clock_isa(struct tm *tm) { static void -read_hardware_clock(const enum clock_access_method method, struct tm *tm){ +read_hardware_clock(const enum clock_access_method method, + const bool universal, bool *valid_p, time_t *systime_p){ /*---------------------------------------------------------------------------- Read the hardware clock and return the current time via argument. Use the method indicated by argument to access the hardware clock. -----------------------------------------------------------------------------*/ + struct tm tm; + + switch (method) { case ISA: - read_hardware_clock_isa(tm); + read_hardware_clock_isa(&tm); break; case RTC_IOCTL: - read_hardware_clock_rtc_ioctl(tm); + read_hardware_clock_rtc_ioctl(&tm); break; case KD: - read_hardware_clock_kd(tm); + read_hardware_clock_kd(&tm); break; default: fprintf(stderr, @@ -893,7 +912,8 @@ read_hardware_clock(const enum clock_access_method method, struct tm *tm){ } if (debug) printf ("Time read from Hardware Clock: %02d:%02d:%02d\n", - tm->tm_hour, tm->tm_min, tm->tm_sec); + tm.tm_hour, tm.tm_min, tm.tm_sec); + mktime_tz(tm, universal, valid_p, systime_p); } @@ -994,14 +1014,13 @@ set_hardware_clock_isa(const struct tm new_broken_time, an ISA Hardware Clock. ----------------------------------------------------------------------------*/ unsigned char save_control, save_freq_select; -#ifdef __i386__ - const bool interrupts_were_enabled = interrupts_enabled; -#endif if (testing) printf("Not setting Hardware Clock because running in test mode.\n"); else { #ifdef __i386__ + const bool interrupts_were_enabled = interrupts_enabled; + __asm__ volatile ("cli"); interrupts_enabled = FALSE; #endif @@ -1220,21 +1239,30 @@ set_epoch(unsigned long epoch, const bool testing, int *retcode_p) { static void -display_time(const time_t systime, const float sync_duration) { +display_time(const bool hclock_valid, const time_t systime, + const float sync_duration) { /*---------------------------------------------------------------------------- Put the time "systime" on standard output in display format. + Except if hclock_valid == false, just tell standard output that we don't + know what time it is. Include in the output the adjustment "sync_duration". -----------------------------------------------------------------------------*/ - char *ctime_now; /* Address of static storage containing time string */ - - /* For some strange reason, ctime() is designed to include a newline - character at the end. We have to remove that. - */ - ctime_now = ctime(&systime); /* Compute display value for time */ - *(ctime_now+strlen(ctime_now)-1) = '\0'; /* Cut off trailing newline */ + if (!hclock_valid) + fprintf(stderr, "The Hardware Clock registers contain values that are " + "either invalid (e.g. 50th day of month) or beyond the range " + "we can handle (e.g. Year 2095).\n"); + else { + char *ctime_now; /* Address of static storage containing time string */ - printf("%s %.6f seconds\n", ctime_now, -(sync_duration)); + /* For some strange reason, ctime() is designed to include a newline + character at the end. We have to remove that. + */ + ctime_now = ctime(&systime); /* Compute display value for time */ + *(ctime_now+strlen(ctime_now)-1) = '\0'; /* Cut off trailing newline */ + + printf("%s %.6f seconds\n", ctime_now, -(sync_duration)); + } } @@ -1322,34 +1350,69 @@ interpret_date_string(const char *date_opt, time_t * const time_p) { static int -set_system_clock(const time_t newtime, const bool testing) { +set_system_clock(const bool hclock_valid, const time_t newtime, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the System Clock to time 'newtime'. + + Also set the kernel time zone value to the value indicated by the + TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as + tzset() would interpret them. Except: do not consider Daylight + Savings Time to be a separate component of the time zone. Include + any effect of DST in the basic timezone value and set the kernel + DST value to 0. - struct timeval tv; + EXCEPT: if hclock_valid is false, just issue an error message + saying there is no valid time in the Hardware Clock to which to set + the system time. + + If 'testing' is true, don't actually update anything -- just say we + would have. +-----------------------------------------------------------------------------*/ int retcode; /* our eventual return code */ - int rc; /* local return code */ - tv.tv_sec = newtime; - tv.tv_usec = 0; - - if (debug) { - printf( "Calling settimeofday:\n" ); - printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n", - (long) tv.tv_sec, (long) tv.tv_usec ); - } - if (testing) { - printf("Not setting system clock because running in test mode.\n"); - retcode = 0; + if (!hclock_valid) { + fprintf(stderr,"The Hardware Clock does not contain a valid time, so " + "we cannot set the System Time from it.\n"); + retcode = 1; } else { - rc = settimeofday(&tv, NULL); - if (rc != 0) { - if (errno == EPERM) - fprintf(stderr, "Must be superuser to set system clock.\n"); - else - fprintf(stderr, - "settimeofday() failed, errno=%d:%s\n", - errno, strerror(errno)); - retcode = 1; - } else retcode = 0; + struct timeval tv; + int rc; /* local return code */ + + tv.tv_sec = newtime; + tv.tv_usec = 0; + + tzset(); /* init timezone, daylight from TZ or ...zoneinfo/localtime */ + /* An undocumented function of tzset() is to set global variabales + 'timezone' and 'daylight' + */ + + if (debug) { + printf( "Calling settimeofday:\n" ); + printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n", + (long) tv.tv_sec, (long) tv.tv_usec ); + } + if (testing) { + printf("Not setting system clock because running in test mode.\n"); + retcode = 0; + } else { + /* For documentation of settimeofday(), in addition to its man page, + see kernel/time.c in the Linux source code. + */ + const struct timezone tz = { timezone/60 - 60*daylight, 0 }; + /* put daylight in minuteswest rather than dsttime, + since the latter is mostly ignored ... */ + rc = settimeofday(&tv, &tz); + if (rc != 0) { + if (errno == EPERM) + fprintf(stderr, "Must be superuser to set system clock.\n"); + else + fprintf(stderr, + "settimeofday() failed, errno=%d:%s\n", + errno, strerror(errno)); + retcode = 1; + } else retcode = 0; + } } return(retcode); } @@ -1358,7 +1421,7 @@ set_system_clock(const time_t newtime, const bool testing) { static void adjust_drift_factor(struct adjtime *adjtime_p, const time_t nowtime, - const time_t hclocktime ) { + const bool hclock_valid, const time_t hclocktime ) { /*--------------------------------------------------------------------------- Update the drift factor in <*adjtime_p> to reflect the fact that the Hardware Clock was calibrated to and before that was set @@ -1372,8 +1435,20 @@ adjust_drift_factor(struct adjtime *adjtime_p, We record in the adjtime file the time at which we last calibrated the clock so we can compute the drift rate each time we calibrate. + EXCEPT: if is false, assume Hardware Clock was not set + before to anything meaningful and regular adjustments have not been + done, so don't adjust the drift factor. + ----------------------------------------------------------------------------*/ - if ((hclocktime - adjtime_p->last_calib_time) >= 24 * 60 * 60) { + if (!hclock_valid) { + if (debug) + printf("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n"); + } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { + if (debug) + printf("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n"); + } else { const float factor_adjust = ((float) (nowtime - hclocktime) / (hclocktime - adjtime_p->last_calib_time)) @@ -1387,18 +1462,15 @@ adjust_drift_factor(struct adjtime *adjtime_p, (int) (hclocktime - adjtime_p->last_calib_time), adjtime_p->drift_factor, factor_adjust ); - + adjtime_p->drift_factor += factor_adjust; - } else if (debug) - printf("Not adjusting drift factor because it has been less than a " - "day since the last calibration.\n"); - + } adjtime_p->last_calib_time = nowtime; adjtime_p->last_adj_time = nowtime; - + adjtime_p->not_adjusted = 0; - + adjtime_p->dirty = TRUE; } @@ -1507,7 +1579,8 @@ save_adjtime(const struct adjtime adjtime, const bool testing) { static void do_adjustment(struct adjtime *adjtime_p, - const time_t hclocktime, const struct timeval read_time, + const bool hclock_valid, const time_t hclocktime, + const struct timeval read_time, const enum clock_access_method clock_access, const bool universal, const bool testing) { /*--------------------------------------------------------------------------- @@ -1515,10 +1588,14 @@ do_adjustment(struct adjtime *adjtime_p, necessary), and 2) updating the last-adjusted time in the adjtime structure. + Do not update anything if the Hardware Clock does not currently present + a valid time. + arguments and are current values from the adjtime file. - is the current time set in the Hardware Clock. + means the Hardware Clock contains a valid time, and that + time is . is the current system time (to be precise, it is the system time at the time was read, which due to computational delay @@ -1534,29 +1611,34 @@ do_adjustment(struct adjtime *adjtime_p, frequently. ----------------------------------------------------------------------------*/ - int adjustment; + if (!hclock_valid) { + fprintf(stderr, "The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n"); + } else { + int adjustment; /* Number of seconds we must insert in the Hardware Clock */ - float retro; + float retro; /* Fraction of second we have to remove from clock after inserting whole seconds. */ - calculate_adjustment(adjtime_p->drift_factor, - adjtime_p->last_adj_time, - adjtime_p->not_adjusted, - hclocktime, - &adjustment, &retro, - debug ); - if (adjustment > 0 || adjustment < -1) { - set_hardware_clock_exact(hclocktime + adjustment, - time_inc(read_time, -retro), - clock_access, universal, testing); - adjtime_p->last_adj_time = hclocktime + adjustment; - adjtime_p->not_adjusted = 0; - adjtime_p->dirty = TRUE; - } else - if (debug) - printf("Needed adjustment is less than one second, " - "so not setting clock.\n"); + calculate_adjustment(adjtime_p->drift_factor, + adjtime_p->last_adj_time, + adjtime_p->not_adjusted, + hclocktime, + &adjustment, &retro, + debug ); + if (adjustment > 0 || adjustment < -1) { + set_hardware_clock_exact(hclocktime + adjustment, + time_inc(read_time, -retro), + clock_access, universal, testing); + adjtime_p->last_adj_time = hclocktime + adjustment; + adjtime_p->not_adjusted = 0; + adjtime_p->dirty = TRUE; + } else + if (debug) + printf("Needed adjustment is less than one second, " + "so not setting clock.\n"); + } } @@ -1659,14 +1741,6 @@ manipulate_clock(const bool show, const bool adjust, ----------------------------------------------------------------------------*/ struct adjtime adjtime; /* Contents of the adjtime file, or what they should be. */ - struct tm tm; - time_t hclocktime; - /* The time the hardware clock had just after we synchronized to its - next clock tick when we started up. - */ - struct timeval read_time; - /* The time at which we read the Hardware Clock */ - int rc; /* local return code */ bool no_auth; /* User lacks necessary authorization to access the clock */ @@ -1674,7 +1748,7 @@ manipulate_clock(const bool show, const bool adjust, rc = i386_iopl(3); if (rc != 0) { fprintf(stderr, MYNAME " is unable to get I/O port access. " - "I.e. iopl(2) returned nonzero return code %d.\n" + "I.e. iopl(3) returned nonzero return code %d.\n" "This is often because the program isn't running " "with superuser privilege, which it needs.\n", rc); @@ -1696,21 +1770,36 @@ manipulate_clock(const bool show, const bool adjust, synchronize_to_clock_tick(clock_access, retcode_p); /* this takes up to 1 second */ if (*retcode_p == 0) { - /* Get current time from Hardware Clock, in case we need it */ + struct timeval read_time; + /* The time at which we read the Hardware Clock */ + + bool hclock_valid; + /* The Hardware Clock gives us a valid time, or at least something + close enough to fool mktime(). + */ + + time_t hclocktime; + /* The time the hardware clock had just after we + synchronized to its next clock tick when we started up. + Defined only if hclock_valid is true. + */ + gettimeofday(&read_time, NULL); - read_hardware_clock(clock_access, &tm); - hclocktime = mktime_tz(tm, universal); + read_hardware_clock(clock_access, universal, &hclock_valid, + &hclocktime); if (show) { - display_time(hclocktime, time_diff(read_time, startup_time)); + display_time(hclock_valid, hclocktime, + time_diff(read_time, startup_time)); *retcode_p = 0; } else if (set) { set_hardware_clock_exact(set_time, startup_time, clock_access, universal, testing); - adjust_drift_factor(&adjtime, set_time, hclocktime); + adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); *retcode_p = 0; } else if (adjust) { - do_adjustment(&adjtime, hclocktime, read_time, clock_access, + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, clock_access, universal, testing); *retcode_p = 0; } else if (systohc) { @@ -1726,9 +1815,10 @@ manipulate_clock(const bool show, const bool adjust, set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, clock_access, universal, testing); *retcode_p = 0; - adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclocktime); + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, + hclocktime); } else if (hctosys) { - rc = set_system_clock(hclocktime, testing); + rc = set_system_clock(hclock_valid, hclocktime, testing); if (rc != 0) { printf("Unable to set system clock.\n"); *retcode_p = 1; @@ -1934,6 +2024,16 @@ main(int argc, char **argv, char **envp) { History of this program: + 98.08.12 BJH Version 2.4 + + Don't use century byte from Hardware Clock. Add comments telling why. + + + 98.06.20 BJH Version 2.3. + + Make --hctosys set the kernel timezone from TZ environment variable + and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com). + 98.03.05 BJH. Version 2.2. Add --getepoch and --setepoch. diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c index eceb0b71..c04b7fd4 100644 --- a/sys-utils/ipcrm.c +++ b/sys-utils/ipcrm.c @@ -6,9 +6,24 @@ #include #include #include + +#include +#include #include #include #include +#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +/* union semun is defined by including */ +#else +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; +#endif + int main(int argc, char **argv) { diff --git a/sys-utils/ipcs.c b/sys-utils/ipcs.c index 9505aff5..975bfd1a 100644 --- a/sys-utils/ipcs.c +++ b/sys-utils/ipcs.c @@ -22,12 +22,38 @@ #include #include #include -#define __KERNEL__ +#if 0 +#define __KERNEL__ /* yuk */ #include +#endif +/* X/OPEN tells us to use for semctl() */ +/* X/OPEN tells us to use for msgctl() */ +/* X/OPEN tells us to use for shmctl() */ +#include +#include #include #include #include +/* The last arg of semctl is a union semun, but where is it defined? + X/OPEN tells us to define it ourselves, but until recently + Linux include files would also define it. */ +#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +/* union semun is defined by including */ +#else +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; +#endif +/* X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm; + libc 4/5 does not mention struct ipc_term at all, but includes + , which defines a struct ipc_perm with such fields. + glibc-1.09 has no support for sysv ipc. + glibc 2 uses __key, __seq */ #if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 #define KEY __key #else @@ -237,7 +263,7 @@ void do_shm (char format) default: printf ("------ Shared Memory Segments --------\n"); - printf ("%-11s%-10s%-10s%-10s%-10s%-10s%-12s\n", "key","shmid", + printf ("%-10s%-10s%-10s%-10s%-10s%-10s%-12s\n", "key","shmid", "owner","perms","bytes","nattch","status"); break; } diff --git a/sys-utils/kbdrate.8 b/sys-utils/kbdrate.8 index 3fef3395..88c6cbc1 100644 --- a/sys-utils/kbdrate.8 +++ b/sys-utils/kbdrate.8 @@ -49,6 +49,13 @@ Not all keyboards have the rates mapped in the same way. Setting the repeat rate on the Gateway AnyKey keyboard does not work. If someone with a Gateway figures out how to program the keyboard, please send mail to faith@cs.unc.edu. +.PP +The above description is for i386 machines, and writing to some io port +won't work on other architectures. Nowadays +.B kbdrate +first tries if the KDKBDREP ioctl is available. If it is, it is used, +otherwise the old method is applied. + .SH FILES .I /etc/rc.local .br diff --git a/sys-utils/kbdrate.c b/sys-utils/kbdrate.c index 07a7e40e..50442945 100644 --- a/sys-utils/kbdrate.c +++ b/sys-utils/kbdrate.c @@ -67,7 +67,7 @@ beats rebuilding the kernel! #include #include #if LINUX_VERSION_CODE >= 131072 -/* Kd.h is not available with all linux versions. 131072 is equivalent +/* kd.h is not available with all linux versions. 131072 is equivalent to linux 2.0.0 */ #include #endif @@ -130,10 +130,15 @@ int main( int argc, char **argv ) } else ioctl_possible = 1; if (ioctl_possible) { - kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */ - if (kbdrep_s.rate < 1) kbdrep_s.rate = 1; + if (rate == 0) /* switch repeat off */ + kbdrep_s.rate = 0; + else + kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */ + if (kbdrep_s.rate < 1) + kbdrep_s.rate = 1; kbdrep_s.delay = delay; - if (kbdrep_s.delay < 1) kbdrep_s.delay = 1; + if (kbdrep_s.delay < 1) + kbdrep_s.delay = 1; if (ioctl( 0, KDKBDREP, &kbdrep_s )) { perror( "ioctl(KDKBDREP)" ); @@ -192,7 +197,7 @@ int main( int argc, char **argv ) valid_rates[value & 0x1f] / 10.0, valid_delays[ (value & 0x60) >> 5 ] ); -#ifdef KDKBREP +#ifdef KDKBDREP } #endif diff --git a/sys-utils/lpcntl.8 b/sys-utils/lpcntl.8 deleted file mode 100644 index 87bcd039..00000000 --- a/sys-utils/lpcntl.8 +++ /dev/null @@ -1,30 +0,0 @@ -.\" Public Domain 1994 Rik Faith (faith@cs.unc.edu) -.\" " -.TH LPCNTL 8 "18 July 1994" "Linux 1.1" "Linux Programmer's Manual" -.SH NAME -lpcntl \- interface to line printer ioctl -.SH SYNOPSIS -.BI "lpcntl " device " [ " irq " ]" -.SH DESCRIPTION -.B lpcntl -is used to manipulate the line printer driver. -.PP -.I device -specifies a line printer device (e.g., -.IR /dev/lp1 ). -.PP -If -.I irq -is specified, then the line printer driver is set to use that IRQ. If the -.I irq -is zero, then the polling driver is selected. Only the super user may -change the IRQ. -.PP -If no -.I irq -is specified, then -.B lpcntl -will report the interrupt number currently in use, or will report that the -polling driver is currently being used. -.SH AUTHOR -Nigel Gamble (nigel@gate.net) diff --git a/sys-utils/lpcntl.c b/sys-utils/lpcntl.c deleted file mode 100644 index bf164a63..00000000 --- a/sys-utils/lpcntl.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Simple command interface to ioctl(fd, LPSETIRQ, irq). - * Nigel Gamble (nigel@gate.net) - * e.g. - * lpcntl /dev/lp1 7 - */ - -#include -#include -#include -#include - -int -main(int argc, char **argv) -{ - unsigned int irq; - int fd; - int ret; - - if (argc < 2) { - fprintf(stderr, "usage: %s []\n", argv[0]); - exit(1); - } - - fd = open(argv[1], O_RDONLY); - if (fd == -1) { - perror(argv[1]); - exit(1); - } - - if (argc == 2) { - irq = ioctl(fd, LPGETIRQ); - if (irq == -1) { - perror(argv[1]); - exit(1); - } - if (irq) - printf("%s using IRQ %d\n", argv[1], irq); - else - printf("%s using polling\n", argv[1]); - } else { - irq = atoi(argv[2]); - ret = ioctl(fd, LPSETIRQ, irq); - if (ret == -1) { - if (errno == EPERM) - fprintf(stderr, "%s: only super-user can change the IRQ\n", argv[0]); - else - perror(argv[1]); - exit(1); - } - } - - return 0; -} diff --git a/sys-utils/sln.1 b/sys-utils/sln.8 similarity index 64% rename from sys-utils/sln.1 rename to sys-utils/sln.8 index a8927193..f97683d4 100644 --- a/sys-utils/sln.1 +++ b/sys-utils/sln.8 @@ -10,13 +10,14 @@ sln \- static ln symbolically links .I dest to -.I source -It is statically linked, needing no dynamic linking at all. This that -sln is usefull to make symbolic links to dynamic libraries if the +.IR source . +It is statically linked, needing no dynamic linking at all. Thus +.B sln +is useful to make symbolic links to dynamic libraries if the dynamic linking system for some reason is nonfunctional. .SH "SEE ALSO" .BR ln(1) .BR ldconfig(8) .BR ld.so(8) -.SH AUTHOR -Mike Parker and David MacKenzie. +.\" .SH AUTHOR +.\" Mike Parker and David MacKenzie. diff --git a/text-utils/Makefile b/text-utils/Makefile index c657be72..686418d6 100644 --- a/text-utils/Makefile +++ b/text-utils/Makefile @@ -11,10 +11,6 @@ include ../MCONFIG MAN1= col.1 colcrt.1 colrm.1 column.1 hexdump.1 more.1 rev.1 \ ul.1 -ifeq "$(HAVE_STRINGS)" "no" -MAN1:=$(MAN1) strings.1 -endif - # Where to put binaries? # See the "install" rule for the links. . . @@ -22,10 +18,6 @@ BIN= more USRBIN= col colcrt colrm column hexdump rev ul -ifeq "$(HAVE_STRINGS)" "no" -USRBIN:=$(USRBIN) strings -endif - # Where to put datebase files? USRLIB= more.help @@ -45,8 +37,7 @@ endif # Rules for hexdump -hexdump: hexdump.o conv.o display.o hexsyntax.o odsyntax.o parse.o \ - $(BSD)/getopt.o +hexdump: hexdump.o conv.o display.o hexsyntax.o odsyntax.o parse.o hexdump.o: hexdump.c hexdump.h conv.o: conv.c hexdump.h display.o: display.c hexdump.h @@ -56,13 +47,13 @@ parse.o: parse.c hexdump.h # Rules for everything else -col: col.o $(BSD)/getopt.o +col: col.o colcrt: colcrt.o colrm: colrm.o -column: column.o $(BSD)/err.o -more.o: more.c $(BSD)/pathnames.h +column: column.o $(ERR_O) +more.o: more.c $(LIB)/pathnames.h rev: rev.o -strings: strings.o $(BSD)/getopt.o + ifeq "$(HAVE_NCURSES)" "yes" more: more.o ul: ul.o diff --git a/text-utils/colcrt.c b/text-utils/colcrt.c index a4d19bb5..f21f7692 100644 --- a/text-utils/colcrt.c +++ b/text-utils/colcrt.c @@ -64,10 +64,11 @@ char printall; char *progname; FILE *f; -int main(int argc, char **argv) +int +main(int argc, char **argv) { - register c; - register char *cp, *dp; + int c; + char *cp, *dp; argc--; progname = *argv++; diff --git a/text-utils/colrm.c b/text-utils/colrm.c index 3051c866..f189e25d 100644 --- a/text-utils/colrm.c +++ b/text-utils/colrm.c @@ -40,9 +40,10 @@ COLRM removes unwanted columns from a file int getn(char *ap); -int main(int argc, char **argv) +int +main(int argc, char **argv) { - register c, ct, first, last; + register int c, ct, first, last; first = 0; last = 0; diff --git a/text-utils/column.c b/text-utils/column.c index 09f52ebb..4ae9522e 100644 --- a/text-utils/column.c +++ b/text-utils/column.c @@ -164,7 +164,6 @@ r_columnate() int base, chcnt, cnt, col, endcol, numcols, numrows, row; maxlength = (maxlength + TAB) & ~(TAB - 1); - /* This could be 0 */ numcols = termwidth / maxlength; if (!numcols) numcols = 1; diff --git a/text-utils/more.c b/text-utils/more.c index 6e076316..24045472 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1980 Regents Of the University of California. + * Copyright (C) 1980 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted @@ -49,6 +49,7 @@ #include #endif #include +#include #define HELPFILE "/usr/lib/more.help" #define VI "/usr/bin/vi" @@ -93,6 +94,8 @@ int get_line(register FILE *f, int *length); void prbuf (register char *s, register int n); int xprintf (char *fmt, ...); void execute (char *filename, char *cmd, ...); +void errwrite (char *txt); +void errwrite1 (char *sym); #define TBUFSIZ 1024 #define LINSIZ 256 @@ -149,7 +152,7 @@ int soglitch; /* terminal has standout mode glitch */ int ulglitch; /* terminal has underline mode glitch */ int pstate = 0; /* current UL state */ char *getenv(); -static magic(); +static int magic(); struct { long chrctr, line; } context, screen_start; @@ -165,7 +168,7 @@ int main(int argc, char **argv) { FILE *f; char *s; char *p; - char ch; + int ch; int left; int prnames = 0; int initopt = 0; @@ -183,6 +186,7 @@ int main(int argc, char **argv) { nfiles = argc; fnames = argv; + setlocale(LC_ALL, ""); initterm (); nscroll = Lpp/2 - 1; if (nscroll <= 0) @@ -286,8 +290,7 @@ int main(int argc, char **argv) { if (firstf) setjmp (restore); if (firstf) { firstf = 0; - if (srchopt) - { + if (srchopt) { search (initbuf, f, 1); if (noscroll) left--; @@ -300,11 +303,12 @@ int main(int argc, char **argv) { left = command (fnames[fnum], f); } if (left != 0) { - if ((noscroll || clearit) && (file_size != LONG_MAX)) + if ((noscroll || clearit) && (file_size != LONG_MAX)) { if (clreol) home (); else doclear (); + } if (prnames) { if (bad_so) erasep (0); @@ -434,21 +438,23 @@ magic(f, fs) FILE *f; char *fs; { - struct exec ex; + char twobytes[2]; - if (fread(&ex, sizeof(ex), 1, f) == 1) - switch(ex.a_info) { - case OMAGIC: - case NMAGIC: - case ZMAGIC: + if (fread(twobytes, 2, 1, f) == 1) { + switch(twobytes[0] + (twobytes[1]<<8)) { + case OMAGIC: /* 0407 */ + case NMAGIC: /* 0410 */ + case ZMAGIC: /* 0413 */ case 0405: case 0411: case 0177545: + case 0x457f: /* simple ELF detection */ xprintf("\n******** %s: Not a text file ********\n\n", fs); (void)fclose(f); return(1); } - (void)fseek(f, 0L, L_SET); /* rewind() not necessary */ + } + (void)fseek(f, 0L, SEEK_SET); /* rewind() not necessary */ return(0); } @@ -547,7 +553,7 @@ void onquit() Pause++; } else if (!dum_opt && notell) { - write (2, "[Use q or Q to quit]", 20); + errwrite("[Use q or Q to quit]"); promptlen += 20; notell = 0; } @@ -597,7 +603,7 @@ void end_it () fflush (stdout); } else - write (2, "\n", 1); + errwrite("\n"); _exit(0); } @@ -682,7 +688,7 @@ void scanstr (int n, char *str) *sptr = '\0'; } -static char my_bell = ctrl('G'); +#define ringbell() errwrite("\007"); #ifdef undef strlen (s) @@ -750,7 +756,7 @@ char *filename; fflush(stdout); } else - write (2, &my_bell, 1); + ringbell(); inwait++; } @@ -787,7 +793,7 @@ int get_line(register FILE *f, int *length) break; } *p++ = c; - if (c == '\t') + if (c == '\t') { if (!hardtabs || (column < promptlen && !hard)) { if (hardtabs && eraseln && !dumb) { column = 1 + (column | 7); @@ -805,9 +811,9 @@ int get_line(register FILE *f, int *length) } else column = 1 + (column | 7); - else if (c == '\b' && column > 0) + } else if (c == '\b' && column > 0) { column--; - else if (c == '\r') { + } else if (c == '\r') { int next = Getc(f); if (next == '\n') { p--; @@ -816,18 +822,16 @@ int get_line(register FILE *f, int *length) } Ungetc(next,f); column = 0; - } - else if (c == '\f' && stop_opt) { + } else if (c == '\f' && stop_opt) { p[-1] = '^'; *p++ = 'L'; column += 2; Pause++; - } - else if (c == EOF) { + } else if (c == EOF) { *length = p - Line; return (column); } - else if (c >= ' ' && c != RUBOUT) + else if (isprint(c)) column++; if (column >= Mcol && fold_opt) break; c = Getc (f); @@ -988,7 +992,7 @@ int command (char *filename, register FILE *f) { register int nlines; register int retval = 0; - register char c; + register int c; char colonch; FILE *helpf; int done; @@ -1030,7 +1034,7 @@ int command (char *filename, register FILE *f) register int initline; if (no_intty) { - write(2, &my_bell, 1); + ringbell(); return (-1); } @@ -1122,7 +1126,7 @@ int command (char *filename, register FILE *f) ret (dlines); } else { - write (2, &my_bell, 1); + ringbell(); break; } case '\'': @@ -1134,7 +1138,7 @@ int command (char *filename, register FILE *f) ret (dlines); } else { - write (2, &my_bell, 1); + ringbell(); break; } case '=': @@ -1151,12 +1155,12 @@ int command (char *filename, register FILE *f) promptlen = 1; fflush (stdout); if (lastp) { - write (2,"\r", 1); + errwrite ("\r"); search (NULL, f, nlines); /* Use previous r.e. */ } else { ttyin (cmdbuf, sizeof(cmdbuf)-2, '/'); - write (2, "\r", 1); + errwrite("\r"); search (cmdbuf, f, nlines); } ret (dlines-1); @@ -1195,7 +1199,7 @@ int command (char *filename, register FILE *f) fflush (stdout); } else - write (2, &my_bell, 1); + ringbell(); break; } if (done) break; @@ -1243,7 +1247,7 @@ int colon (char *filename, int cmd, int nlines) return (0); case 'p': if (no_intty) { - write (2, &my_bell, 1); + ringbell(); return (-1); } putchar ('\r'); @@ -1259,7 +1263,7 @@ int colon (char *filename, int cmd, int nlines) case 'Q': end_it (); default: - write (2, &my_bell, 1); + ringbell(); return (-1); } } @@ -1276,7 +1280,7 @@ int number(char *cmd) i = 0; ch = otty.c_cc[VKILL]; for (;;) { ch = readch (); - if (ch >= '0' && ch <= '9') + if (isdigit(ch)) i = i*10 + ch - '0'; else if (ch == otty.c_cc[VKILL]) i = 0; @@ -1306,7 +1310,7 @@ void do_shell (char *filename) } } fflush (stdout); - write (2, "\n", 1); + errwrite("\n"); promptlen = 0; shellp = 1; execute (filename, shell, shell, "-c", shell_line, 0); @@ -1337,7 +1341,7 @@ void search(char buf[], FILE *file, register int n) line1 = Ftell (file); rdline (file); lncount++; - if ((rv = re_exec (Line)) == 1) + if ((rv = re_exec (Line)) == 1) { if (--n == 0) { if (lncount > 3 || (lncount > 1 && no_intty)) { @@ -1349,29 +1353,31 @@ void search(char buf[], FILE *file, register int n) if (!no_intty) { Currline -= (lncount >= 3 ? 3 : lncount); Fseek (file, line3); - if (noscroll) + if (noscroll) { if (clreol) { home (); cleareol (); } else doclear (); + } } else { kill_line (); - if (noscroll) + if (noscroll) { if (clreol) { home (); cleareol (); } else doclear (); + } pr (Line); putchar ('\n'); } break; } - else if (rv == -1) + } else if (rv == -1) error ("Regular expression botch"); } if (feof (file)) { @@ -1435,7 +1441,7 @@ void execute (char * filename, char * cmd, ...) va_end(argp); /* balance {}'s for some UNIX's */ execv (cmd, args); - write (2, "exec failed\n", 12); + errwrite("exec failed\n"); exit (1); } if (id > 0) { @@ -1449,7 +1455,7 @@ void execute (char * filename, char * cmd, ...) if (catch_susp) signal(SIGTSTP, onsusp); } else - write(2, "can't fork\n", 11); + errwrite("can't fork\n"); set_tty (); pr ("------------------------\n"); prompt (filename); @@ -1460,7 +1466,7 @@ void execute (char * filename, char * cmd, ...) void skiplns (register int n, register FILE *f) { - register char c; + register int c; while (n > 0) { while ((c = Getc (f)) != '\n') @@ -1636,22 +1642,23 @@ int readch () extern int errno; errno = 0; - if (read (2, &ch, 1) <= 0) + if (read (2, &ch, 1) <= 0) { if (errno != EINTR) end_it(); else ch = otty.c_cc[VKILL]; + } return (ch); } -static char BS = '\b'; +static char *BS = "\b"; static char *BSB = "\b \b"; -static char CARAT = '^'; +static char *CARAT = "^"; #define ERASEONECHAR \ if (docrterase) \ - write (2, BSB, sizeof(BSB)); \ + errwrite(BSB); \ else \ - write (2, &BS, sizeof(BS)); + errwrite(BS); void ttyin (char buf[], register int nmax, char pchar) { @@ -1698,7 +1705,7 @@ void ttyin (char buf[], register int nmax, char pchar) erasep (1); else if (docrtkill) while (promptlen-- > 1) - write (2, BSB, sizeof(BSB)); + errwrite(BSB); promptlen = 1; } sptr = buf; @@ -1714,12 +1721,12 @@ void ttyin (char buf[], register int nmax, char pchar) *sptr++ = ch; if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { ch += ch == RUBOUT ? -0100 : 0100; - write (2, &CARAT, 1); + errwrite(CARAT); promptlen++; } cbuf = ch; if (ch != '\n' && ch != ESC) { - write (2, &cbuf, 1); + errwrite1(&cbuf); promptlen++; } else @@ -1778,14 +1785,24 @@ void show (register char ch) if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { ch += ch == RUBOUT ? -0100 : 0100; - write (2, &CARAT, 1); + errwrite(CARAT); promptlen++; } cbuf = ch; - write (2, &cbuf, 1); + errwrite1(&cbuf); promptlen++; } +void errwrite (char *txt) +{ + write (fileno(stderr), txt, strlen(txt)); +} + +void errwrite1 (char *sym) +{ + write (fileno(stderr), sym, 1); +} + void error (char *mess) { if (clreol) @@ -1809,6 +1826,8 @@ void error (char *mess) void set_tty () { otty.c_lflag &= ~(ICANON|ECHO); + otty.c_cc[VMIN] = 1; /* read at least 1 char */ + otty.c_cc[VTIME] = 0; /* no timeout */ stty(fileno(stderr), &otty); } @@ -1826,12 +1845,14 @@ void reset_tty () pstate = 0; } otty.c_lflag |= ICANON|ECHO; + otty.c_cc[VMIN] = savetty0.c_cc[VMIN]; + otty.c_cc[VTIME] = savetty0.c_cc[VTIME]; stty(fileno(stderr), &savetty0); } void rdline (register FILE *f) { - register char c; + register int c; register char *p; p = Line; diff --git a/text-utils/ul.c b/text-utils/ul.c index f10d2245..8da3b3f7 100644 --- a/text-utils/ul.c +++ b/text-utils/ul.c @@ -41,6 +41,7 @@ #include /* for bzero() */ #include /* for setupterm() */ #include /* for getenv() */ +#include /* for INT_MAX */ void filter(FILE *f); void flushln(void); @@ -52,6 +53,7 @@ void reverse(void); void initinfo(void); void outc(int c); void setmode(int newmode); +void setcol(int newcol); #define IESC '\033' #define SO '\016' @@ -59,7 +61,6 @@ void setmode(int newmode); #define HFWD '9' #define HREV '8' #define FREV '7' -#define MAXBUF 512 #define NORMAL 000 #define ALTSET 001 /* Reverse */ @@ -67,6 +68,7 @@ void setmode(int newmode); #define SUBSC 004 /* Dim | Ul */ #define UNDERL 010 /* Ul */ #define BOLD 020 /* Bold */ +#define INITBUF 512 int must_use_uc, must_overstrike; char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, @@ -78,7 +80,8 @@ struct CHAR { char c_char; } ; -struct CHAR obuf[MAXBUF]; +struct CHAR *obuf; +int obuflen; /* Tracks number of elements in obuf. */ int col, maxcol; int mode; int halfpos; @@ -150,23 +153,20 @@ int main(int argc, char **argv) void filter(FILE *f) { - register c; + int c; while ((c = getc(f)) != EOF) switch(c) { case '\b': - if (col > 0) - col--; + setcol(col - 1); continue; case '\t': - col = (col+8) & ~07; - if (col > maxcol) - maxcol = col; + setcol((col+8) & ~07); continue; case '\r': - col = 0; + setcol(0); continue; case SO: @@ -224,9 +224,7 @@ void filter(FILE *f) else obuf[col].c_char = '_'; case ' ': - col++; - if (col > maxcol) - maxcol = col; + setcol(col + 1); continue; case '\n': @@ -251,9 +249,7 @@ void filter(FILE *f) obuf[col].c_mode |= BOLD|mode; else obuf[col].c_mode = mode; - col++; - if (col > maxcol) - maxcol = col; + setcol(col + 1); continue; } if (maxcol) @@ -262,8 +258,8 @@ void filter(FILE *f) void flushln() { - register lastmode; - register i; + int lastmode; + int i; int hadmodes = 0; lastmode = NORMAL; @@ -274,9 +270,9 @@ void flushln() lastmode = obuf[i].c_mode; } if (obuf[i].c_char == '\0') { - if (upln) + if (upln) { PRINT(CURS_RIGHT); - else + } else outc(' '); } else outc(obuf[i].c_char); @@ -361,21 +357,30 @@ void iattr() void initbuf() { + if (obuf == NULL) { /* First time. */ + obuflen = INITBUF; + obuf = malloc(sizeof(struct CHAR) * obuflen); + if (obuf == NULL) { + fprintf(stderr, "Unable to allocate buffer.\n"); + exit(1); + } + } - bzero((char *)obuf, sizeof (obuf)); /* depends on NORMAL == 0 */ - col = 0; + /* assumes NORMAL == 0 */ + bzero((char *)obuf, sizeof(struct CHAR) * obuflen); + setcol(0); maxcol = 0; mode &= ALTSET; } void fwd() { - register oldcol, oldmax; + int oldcol, oldmax; oldcol = col; oldmax = maxcol; flushln(); - col = oldcol; + setcol(oldcol); maxcol = oldmax; } @@ -390,7 +395,7 @@ void reverse() void initinfo() { - char *getenv(), *tigetstr(); + char *tigetstr(); CURS_UP = tigetstr("cuu1"); CURS_RIGHT = tigetstr("cuf1"); @@ -495,3 +500,40 @@ void setmode(int newmode) } curmode = newmode; } + + + + +void setcol(int newcol) +{ + col = newcol; + + if (col < 0) + col = 0; + else if (col > maxcol) { + maxcol = col; + + /* If col >= obuflen, expand obuf until obuflen > col. */ + while (col >= obuflen) { + /* Paranoid check for obuflen == INT_MAX. */ + if (obuflen == INT_MAX) { + fprintf(stderr, + "Input line too long.\n"); + exit(1); + } + + /* Similar paranoia: double only up to INT_MAX. */ + obuflen = ((INT_MAX / 2) < obuflen) + ? INT_MAX + : obuflen * 2; + + /* Now we can try to expand obuf. */ + obuf = realloc(obuf, sizeof(struct CHAR) * obuflen); + if (obuf == NULL) { + fprintf(stderr, + "Out of memory when growing buffer.\n"); + exit(1); + } + } + } +} diff --git a/uio.h-diff b/uio.h-diff deleted file mode 100644 index 48be527b..00000000 --- a/uio.h-diff +++ /dev/null @@ -1,20 +0,0 @@ ---- /usr/include/sys/uio.h~ Sun Jan 24 20:02:24 1993 -+++ /usr/include/sys/uio.h Thu Oct 12 12:29:00 1995 -@@ -32,6 +32,7 @@ - - /* Structure describing a section of memory. */ - -+#if 0 - struct iovec - { - /* Starting address. */ -@@ -39,6 +40,9 @@ - /* Length in bytes. */ - size_t iov_len; - }; -+#else -+#include -+#endif - - - __BEGIN_DECLS diff --git a/util-linux-2.1.Announce b/util-linux-2.1.Announce deleted file mode 100644 index 0906617e..00000000 --- a/util-linux-2.1.Announce +++ /dev/null @@ -1,48 +0,0 @@ - -util-linux-2.1.tar.gz (source distribution) -util-linux-2.1.bin.tar.gz (binary distribution) - - WARNING: THIS COLLECTION DOES *NOT* SUPPORT SHADOW PASSWORDS. - - WARNING: THIS COLLECTION DOES *NOT* SUPPORT SYSTEM V INITTAB. - - WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY! - - WARNING: DO *NOT* INSTALL WITHOUT THINKING. - - WARNING: *READ* the util-linux-2.1.bin.Notes file *BEFORE* and *AFTER* - installation: there are a few links you must make by hand. - - This is a collection of many assorted utilities for Linux. Some are - system utilities that are not easily available anywhere elsewhere - (e.g., mkfs.minix, mkswap); others are BSD ports of common utilities - that are not yet contained in any FSF package (e.g., col); others are - non-System-V alternatives to common utilities (e.g., simpleinit, - agetty, login, passwd). - - The arrangement, as nearly as I can determine, conforms to the Linux - Filesystem Structure, Interim Release 1.1, October 9, 1994, with *NO* - exceptions. A copy of the standards document can be found at - tsx-11.mit.edu:/pub/linux/docs/linux-standards/fsstnd/*. - - Many people provided patches and suggestions. I deeply appreciate - this. - - -HIGHLIGHTS for version 2.1: - -1) Directory structure rearrange, with configuration support for those who - use shadow passwords and System V init (no support is provided for these - things, but your utilities won't get overwritten if you do a "make - install" after you properly edit MCONFIG). -2) fdisk and cfdisk should work as expected with 2GB+ disk drives -3) As usual, lots of stuff was updated and added, including mount, vipw, - readprofile -4) Some stuff was also deleted, and can now be found elsewhere: - fsck wrapper: tsx-11.mit.edu:/pub/linux/ALPHA/ext2fs/e2fsprogs* - pwd, su: prep.ai.mit.edu:/pub/gnu/sh-utils* - ed: prep.ai.mit.edu:/pub/gnu/ed* - od: prep.ai.mit.edu:/pub/gnu/textutils* - uudecode/uuencode: prep.ai.mit.edu:/pub/gnu/sharutils* - bdflush/update: ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/v1.1/bdflush* - diff --git a/util-linux-2.1.bin.Notes b/util-linux-2.1.bin.Notes deleted file mode 100644 index a2ac394c..00000000 --- a/util-linux-2.1.bin.Notes +++ /dev/null @@ -1,549 +0,0 @@ -util-linux: Miscellaneous utilities for Linux -%n util-linux -%v 2.1 -%c * -%l * -%b * -%d * -%f ftp.cs.unc.edu:/pub/users/faith/linux/utils -%t util-linux-2.1.tar.gz -%w utils -%% -# These lines describe an automated build procedure, please ignore them. -%setup -make -%doc COPYING.GPL COPYING.UCB -%doc ./time/README.time ./disk-utils/README.cfdisk -%doc ./disk-utils/README.fdisk ./disk-utils/README.bootutils-0.1 -%doc ./sys-utils/README.setserial ./makedev-1.4.1/README.MAKEDEV-C -%doc ./misc-utils/README.script ./misc-utils/README.hostname -%doc ./misc-utils/README.namei ./misc-utils/README.cal -%doc ./misc-utils/README1.namei ./text-utils/README.col -%doc ./mount/README.mount ./selection/README.selection -%doc ./login-utils/README.getty ./login-utils/README.admutil -%doc ./login-utils/README.poeigl -%doc util-linux-$VERSION.Announce util-linux-$VERSION.lsm -cp -a $BUILDDIR/$NAME-$VERSION/example.files /usr/doc/$WHERE/$NAME-$VERSION -* rm -rf /usr/lib/zoneinfo -* make install -%i set -x -%i /usr/sbin/zic -l US/Eastern -%i /usr/sbin/zic -p America/New_York -%i set +x -%i echo 'WARNING: Check time zone! (If necessary, change with zic).' -%i echo 'WARNING: Check /etc/rc for initalization of /var/adm/utmp' -%i echo 'WARNING: /etc/rc should run /sbin/update, *NOT* /sbin/bdflush' -exit -# Please ignore the previous lines. . . -# The informative part of the notes file starts here: - -WARNING: THE PROGRAMS IN THIS SUITE DO *NOT* SUPPORT SHADOW PASSWORD FILES! - -WARNING: THIS COLLECTION DOES *NOT* SUPPORT SYSTEM V INITTAB. - -WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY! - -WARNING: DO *NOT* INSTALL WITHOUT THINKING. - -WARNING: Read the util-linux-2.1.bin.Notes file *BEFORE* and *AFTER* - installation: there are a few links you must make by hand. - -WARNING: The agetty, simpleinit, login, passwd, and other programs in this - package are *NOT* System V compliant. These utilities are meant - to be used by people who build their own systems. If you are not - a wizard, do *NOT* blindly install these utilities: they could - prevent you from logging into your system. Have a boot floppy - ready, especially if you don't know what you are doing. - -WARNING: The binary distribution was tarred using GNU TAR AND THE -S OPTION! - This means that holes will be preserved, but that ONLY GNU TAR - WILL WORK ON THE BINARY DISTRIBUTION (in fact, other, inferior, - tar programs will fail silently). YOU HAVE BEEN WARNED! - -WARNING: localtime and posixtime default to US/Eastern -- change these now. - - - -To install from the binary distribution: - -1) Get binary distribution (see the .lsm file for locations) -2) cd / -3) gtar zpxvf util-linux-2.1.bin.tar.gz - (or: pms -i util-linux-2.1.bin.tar.gz) -4) *IF* you want to use agetty and simpleinit, then make softlinks from - /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure - that your /etc/inittab is set up right (this is *NOT* the System V - compatible init!), or you will be hosed. -5) Run zic -l and/or zic -p to set your timezone. The distribution is set - up to use /usr/lib/zoneinfo/US/Eastern as the default. This was - installed with "zic -l US/Eastern" -6) Remove all the old binaries from previous locations. - - - -To install from source: - -1) Get source distribution (see the .lsm file for locations) -2) Untar util-linux-2.1.tar.gz in /usr/src -3) cd util-linux-2.1 -4) Edit MCONFIG: - - If you use the shadow password suite and do _not_ want to install - programs like login and passwd that do not support shadow passwords, - then set HAVE_SHADOW to yes - - If you use the System V init suite and do _not_ want to install programs - like agetty, simpleinit, and shutdown, then set HAVE_SYSVINIT to yes - - If you don't like the compile-time options or the directories, then - change them. Note that you also can say something like "make OPT=-g - LDFLAGS=" in order to make a complete debugging version without editing - the MCONFIG at all. - -5) make -6) make install -7) If you want to use simpleinit and agetty, then make softlinks from - /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure - that your /etc/inittab is set up right (this is *NOT* the System V - compatible init!), or you will be hosed. If you are using the SysV - init and/or some other getty, they you can keep using those. -8) Run zic -l and/or zic -p to set your timezone. The distribution is set - up to use /usr/lib/zoneinfo/US/Eastern as the default. This was - installed with "zic -l US/Eastern" -9) Remove all the old binaries from previous locations. - - - -HIGHLIGHTS for version 2.1: - -1) Directory structure rearrange, with configuration support for those who - use shadow passwords and System V init (no support is provided for these - things, but your utilities won't get overwritten if you do a "make - install" after you properly edit MCONFIG). -2) fdisk and cfdisk should work as expected with 2GB+ disk drives -3) As usual, lots of stuff was updated and added, including mount, vipw, - readprofile -4) Some stuff was also deleted, and can now be found elsewhere: - fsck wrapper: tsx-11.mit.edu:/pub/linux/ALPHA/ext2fs/e2fsprogs* - pwd, su: prep.ai.mit.edu:/pub/gnu/sh-utils* - ed: prep.ai.mit.edu:/pub/gnu/ed* - od: prep.ai.mit.edu:/pub/gnu/textutils* - uudecode/uuencode: prep.ai.mit.edu:/pub/gnu/sharutils* - bdflush/update: ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/v1.1/bdflush* - - - -PARTIAL HISTORY OF UTIL-LINUX: - -bsd: - Nothing in this directory gets installed, but some BSD programs need - this support: - err.c: 8.1 (Berkeley) 6/4/93 - err.h: 8.1 (Berkeley) 6/2/93 - getopt.c: 4.13 (Berkeley) 2/23/91 - pathnames.h: 5.3 (Berkeley) 5/9/89 with extensive modifications for - Linux - -disk-utils: - cfdisk: 0.8 BETA (>2GB) from Kevin E. Martin (martin@cs.unc.edu) with - modifications for disks > 2GB. - ftp.cs.unc.edu:/pub/users/martin/linux/cfdisk-0.8.tar.gz - fdformat: Werner Almesberger (almesber@nessie.cs.id.ethz.ch), with - modifications by Marcel Mol (marcel@dutecad.et.tudelft.nl)). - Later, updated with a September 1992 version by Werner. - fdisk: A. V. Le Blanc (LeBlanc@mcc.ac.uk) fdisk 1.5 release, with - patched from Kevin Martin for DOS and OS/2 compatibility (1.5a); - Rik Faith (1.5b, 2.0). - frag: Werner Almesberger (1.0), Steffen Zahn (1.1), Rob Hooft (1.2), - Steffen Zahn (szahn%masterix@emndev.siemens.co.at) (1.3), Michael - Bischoff (1.4). - fsck.minix, mkfs.minix: Linus Torvalds, with modifications by: Rik - Faith (faith@cs.unc.edu), Scott Heavner - (sdh@po.cwru.edu), Dr. Wettstein - (greg%wind.uucp@plains.nodak.edu), Daniel - Quinlan (quinlan@yggdrasil.com). - mkswap: Linus Torvalds, with modifications by Mike Jagdis - (jaggy@purplet.demon.co.uk. ) - setfdprm: Werner Almesberger (almesber@nessie.cs.id.ethz.ch) - llseek.c: from Remy Card's e2fsprogs-0.5b-WIP.tar.gz - -games: - banner: (8.3 (Berkeley) 4/2/94) - ddate: Druel the Chaotic aka Jeremy Johnson aka mpython@gnu.ai.mit.edu, - with modifications by Lee Harvey Oswald Smith, K.S.C. - -login-utils: - agetty: W. Z. Venema, ported by Peter Orbaek . - ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz - chfn: Salvatore Valente - chsh: Salvatore Valente - last: 5.11 w/year (Berkeley) 6/29/88; Port by Michael Haardt with - changes by Peter Orbaek. - ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz - login: 5.40 (Berkeley) 5/9/89; with ports by Michael Glad and Peter Orbaek - ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz - mesg: Miquel van Smoorenburg (miquels@htsa.aha.nl, - miquels@drinkel.nl.mugnet.org). From his sysvinit.tar.Z package. - newgrp: Michael Haardt, with modifications by Peter Orbaek. - ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz - passwd: Peter Orbaek, with yp modifications by Alvaro Martinez - Echevarria (alvaro@enano.etsit.upm.es) - ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz - shutdown: Peter Orbaek, with new modifications by Stephen Tweedie, Rik - Faith, and Dave (gentzel@nova.enet.dec.com). - ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz - simpleinit: Peter Orbaek - ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz - vipw: 5.16 (Berkeley) 3/3/91, with modifications by Mike Grupenhoff - - wall: 5.14 (Berkeley) 3/2/91 [From the BSD NET-2 (4.3bsd-reno) - distribution at wuarchive.wustl.edu:/mirrors/4.3-reno] - -makedev-1.4: - MAKEDEV-C: David A. Holland (dholland@husc.harvard.edu) - This version MODIFIED by Rik Faith (faith@cs.unc.edu) - sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-C-1.4.tar.gz - - -misc-utils: - cal: 8.4 (Berkeley) 4/2/94, with modifications by Rik Faith and - Hein@student.tu-clausthal.de (Jochen Hein). - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - clear: Rik Faith - domainname: Peter Orbaek - ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz - dsplit: David Arnstein (arnstein@netcom.com) - gatekeeper.dec.com:/pub/usenet/comp.sources.misc/volume40/dsplit - getopt (getoptprog): jhunix.hcf.jhu.edu: - /pub/public_domain_software/NetBSD/usr/src/usr.bin/getopt - hostid: Mitch DSouza (m.dsouza@mrc-apu.cam.ac.uk) - ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz - hostname/dnsdomainname: Peter Tobias - This version (1.6) should also be available soon in: - nic.funet.fi:/pub/OS/Linux/PEOPLE/Linus/net-source/base/NetKit-A* - kill: BSD version, modified by Salvatore Valente - logger: 8.1 (Berkeley) 6/6/93, with modifications by Rik Faith - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - look.c: 8.1 (Berkeley) 6/14/93, with modifications by Rik Faith - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - mcookie: Rik Faith (faith@cs.unc.edu) - md5sum: Branki Lankester and Colin Plumb. The MD5 message-digest - algorithm is in the Public Domain. This implementation - calculates message-digest information only, and can NOT be used - for encryption. Therefore it is exportable from the USA. - Original sources in the MIT version of PGP 2.6.2. - namei: Roger S. Southwick, with modifications by Steve Tell. - reset: Rik Faith - script: 5.13 (Berkeley) 3/5/91, with modifications by Rick Sladkey - (jrs@world.std.com), Harald Koenig - (koenig@nova.tat.physik.uni-tuebingen.de). - setterm: Gordon Irlam (gordoni@cs.ua.oz.au), with modifications by - Peter MacDonald, Mika Liljeberg (liljeber@cs.Helsinki.FI), - John Walder (j-walder@uiuc.edu) [for dosemu]. - tsort: 5.3 (Berkeley) 6/1/90 - wuarchive.wustl.edu:/mirrors/4.3-reno - whereis: 5.5 (Berkeley) 4/18/91 - wuarchive.wustl.edu:/mirrors/4.3-reno - write: 4.22 (Berkeley) 6/1/90, with modifications by Mike Grupenhoff - (kashmir@umiacs.umd.edu) . - wuarchive.wustl.edu:/mirrors/4.3-reno - -mount: - mount, umount, swapon - - Rick Sladkey put together the mount-0.99.6.tar.Z package, and Stephen - Tweedie provided updates. The utilities were originally from that - package (all appear to be by Doug Quale (quale@saavik.cs.wisc.edu), - with modifications by H. J. Lu (hlu@eecs.wsu.edu) on 11/25/92; Rick - Sladkey (jrs@world.std.com) in January 1993; and Stephen Tweedie - on 8 October 1993. This distribution mount now - supports NFS stuff. I have modified the man pages. I have also added - a small patch from Hamish Glen Coleman (t933093@minyos.xx.rmit.OZ.AU) - which restores the -o semantics. - - Updated with Rick Sladkey's mount-0.99.14.tar.gz package, and with - extra patches from Rick. Adam J. Richter allowed -t option to be - optional. Patrick J. Volkerding (volkerdi@mhd1.moorhead.msus.edu) and - Mitchum DSouza both provided patches that fixed the (null) problem when - not using -t. Mitchum DSouza - (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for loop - device mounts. Sebastian Lederer - (lederer@next-pc.informatik.uni-bonn.de) added support for sending an - unmount RPC call to the server when an NFS-filesystem is unmounted. - Sander van Malssen (svm@kozmix.hacktic.nl) added support for remounting - readonly file systems readonly. Mike Grupenhoff - added a probe of the superblock for the type - before /proc/filesystems is checked. Andries.Brouwer@cwi.nl fixed up - error reporting. - -selection: - The complete selection-1.5 package, by Andrew Haylett - , 17th June 1993, is included. Kernel patches are - no longer necessary for modern kernels, but these were tiny so I left - them in for historical reasons. The Makefile was modified for this - distribution. With changes from Rick Sladkey. - -sys-utils: - MAKEDEV: Nick Holloway - arch: Rik Faith - chroot: Rick Sladkey - clock: Originally from the timesrc-1.2.tar.Z package, Charles Hedrick, - hedrick@cs.rutgers.edu (V1.0); Rob Hooft, hooft@chem.ruu.nl - (V1.1); Harald Koenig (koenig@nova.tat.physik.uni-tuebingen.de) - (V1.2). With additional changes: Hamish Coleman - (hamish@zot.apana.org.au) (V1.2a); Alan Modra - (alan@spri.levels.unisa.edu.au (V1.3, V1.4). - ctrlaltdel: Peter Orbaek - ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz - dmesg: Theodore Ts'o (tytso@athena.mit.edu); Rick Sladkey - (jrs@world.std.com) - ipcrm: From the ipcdelta.tar.z distribution by krishna - balasub@cis.ohio-state.edu on 3/15/93. ipc.info and ipc.texi - are also from that distribution. - ipcs: Also from the ipcdelta.tar.z distribution by krishna - balasub@cis.ohio-state.edu, with patches from Mike Jagdis - (jaggy@purplet.demon.co.uk) - kbdrate: Rik Faith (faith@cs.unc.edu), with patches from - Andries.Brouwer@cwi.nl and John Bowman - (bowman@hagar.ph.utexas.edu) - lpcntl: Nigel Gamble (nigel@gate.net) - rdev: almesber@nessie.cs.id.ethz.ch (Werner Almesberger), with - modifications from Peter MacDonald, Stephen Tweedie - (sct@dcs.ed.ac.uk), and Dave (gentzel@nova.enet.dec.com) - readprofile: Alessandro Rubini - renice: 8.1 (Berkeley) 6/9/93 - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - setserial: Michael K. Johnson (johnsonm@stolaf.edu) re-released Rick - Sladkey's setserial in January 1993, with changes by - Theodore Ts'o (tytso@mit.edu). I think that Theodore also - did extensive changes for version 2.01, I can't find any - notes about this in the documentation. However, Theodore - Ts'o (tytso@ATHENA.MIT.EDU) released version 2.10, and that - is now included. - setsid: Rick Sladkey - sln: Mike Parker and David MacKenzie (from Linux's libc) - sync: Nick Holloway, with thanks to James Bonfield - tunelp: Michael K. Johnson (johnsonm@nigel.vnet.net) - update_state: Rik Faith (faith@cs.unc.edu) - -syslogd: - 5.45 (Berkeley) 3/2/91 - - Most of the changes for syslogd come from Rick Sladkey - (jrs@world.std.com), but I'd like to thank other people who sent in - changes (which usually got forwarded to Rick): Carsten Paeth - (calle@calle.in-berlin.de) and Kaz Sasayama (kaz@lilia.iijnet.or.jp). - -text-utils: - col: 5.3 (Berkeley) 2/2/91; with patches from Andries.Brouwer@cwi.nl - and Carl Christofferson (cchris@connected.com) - wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin} - colcrt: 8.1 (Berkeley) 6/6/93 (Bill Joy) - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - colrm: 5.4 (Berkeley) 6/1/90 (Jeff Schriebman) - column: 8.3 (Berkeley) 4/2/94 - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - hexdump: 5.5 (Berkeley) 6/1/90 - wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin} - more: 5.19 (Berkeley) 6/29/88 (Eric Shienbrood, Geoff Peck, John Foderaro) - rev: 5.2 (Berkeley) 3/21/92; with modifications by Charles Hannum - (mycroft@gnu.ai.mit.edu), Brian Koehmstedt (bpk@gnu.ai.mit.edu), - bjdouma@xs4all.nl - wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin} - strings: 5.10 (Berkeley) 5/23/91; with patches from Vitor Duarte - - wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin} - ul: 8.1 (Berkeley) 6/6/93 - ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin - -time: - elsie.nci.nih.gov:/pub/classictzcode.tar.gz - elsie.nci.nih.gov:/pub/classictzdata.tar.gz - (The zoneinfo database was updated Dec 1994.) - -%% -* bin/arch -* bin/dmesg -* bin/dnsdomainname -* bin/domainname -* bin/hostname -* bin/kill -* bin/login -* bin/more -* bin/mount -* bin/setserial -* bin/sync -* bin/umount -* dev/MAKEDEV -* dev/MAKEDEV-C -* etc/DEVINFO -* etc/MAKEDEV.cfg -* etc/fdprm -* sbin/agetty -* sbin/cfdisk -* sbin/clock -* sbin/fastboot -* sbin/fasthalt -* sbin/fdisk -* sbin/fsck.minix -* sbin/halt -* sbin/kbdrate -* sbin/mkfs.minix -* sbin/mkswap -* sbin/reboot -* sbin/shutdown -* sbin/simpleinit -* sbin/sln -* sbin/swapoff -* sbin/swapon -* usr/bin/cal -* usr/bin/chfn -* usr/bin/chsh -* usr/bin/clear -* usr/bin/col -* usr/bin/colcrt -* usr/bin/colrm -* usr/bin/column -* usr/bin/dsplit -* usr/bin/fdformat -* usr/bin/getopt -* usr/bin/hexdump -* usr/bin/hostid -* usr/bin/ipcrm -* usr/bin/ipcs -* usr/bin/last -* usr/bin/logger -* usr/bin/look -* usr/bin/lpcntl -* usr/bin/mcookie -* usr/bin/md5sum -* usr/bin/mesg -* usr/bin/namei -* usr/bin/newgrp -* usr/bin/passwd -* usr/bin/ramsize -* usr/bin/rdev -* usr/bin/readprofile -* usr/bin/renice -* usr/bin/reset -* usr/bin/rev -* usr/bin/rootflags -* usr/bin/script -* usr/bin/selection -* usr/bin/setfdprm -* usr/bin/setsid -* usr/bin/setterm -* usr/bin/strings -* usr/bin/swapdev -* usr/bin/tsort -* usr/bin/tunelp -* usr/bin/ul -* usr/bin/vidmode -* usr/bin/wall -* usr/bin/whereis -* usr/bin/write -* usr/info/ipc.info -* usr/lib/libz.a -* usr/lib/more.help -* usr/lib/zoneinfo -* usr/man/man1/arch.1 -* usr/man/man1/cal.1 -* usr/man/man1/chfn.1 -* usr/man/man1/chsh.1 -* usr/man/man1/clear.1 -* usr/man/man1/col.1 -* usr/man/man1/colcrt.1 -* usr/man/man1/colrm.1 -* usr/man/man1/column.1 -* usr/man/man1/dnsdomainname.1 -* usr/man/man1/domainname.1 -* usr/man/man1/dsplit.1 -* usr/man/man1/getopt.1 -* usr/man/man1/hexdump.1 -* usr/man/man1/hostid.1 -* usr/man/man1/hostname.1 -* usr/man/man1/kill.1 -* usr/man/man1/last.1 -* usr/man/man1/logger.1 -* usr/man/man1/login.1 -* usr/man/man1/look.1 -* usr/man/man1/md5sum.1 -* usr/man/man1/mesg.1 -* usr/man/man1/more.1 -* usr/man/man1/namei.1 -* usr/man/man1/newgrp.1 -* usr/man/man1/passwd.1 -* usr/man/man1/readprofile.1 -* usr/man/man1/reset.1 -* usr/man/man1/rev.1 -* usr/man/man1/script.1 -* usr/man/man1/selection.1 -* usr/man/man1/setterm.1 -* usr/man/man1/strings.1 -* usr/man/man1/tsort.1 -* usr/man/man1/ul.1 -* usr/man/man1/wall.1 -* usr/man/man1/whereis.1 -* usr/man/man1/write.1 -* usr/man/man3/newctime.3 -* usr/man/man3/newtzset.3 -* usr/man/man5/DEVINFO.5 -* usr/man/man5/MAKEDEV.cfg.5 -* usr/man/man5/fstab.5 -* usr/man/man5/nfs.5 -* usr/man/man5/syslog.conf.5 -* usr/man/man5/tzfile.5 -* usr/man/man6/banner.6 -* usr/man/man6/ddate.6 -* usr/man/man8/MAKEDEV-C.8 -* usr/man/man8/MAKEDEV.8 -* usr/man/man8/agetty.8 -* usr/man/man8/cfdisk.8 -* usr/man/man8/chroot.8 -* usr/man/man8/clock.8 -* usr/man/man8/ctrlaltdel.8 -* usr/man/man8/dmesg.8 -* usr/man/man8/fastboot.8 -* usr/man/man8/fasthalt.8 -* usr/man/man8/fdformat.8 -* usr/man/man8/fdisk.8 -* usr/man/man8/frag.8 -* usr/man/man8/fsck.minix.8 -* usr/man/man8/halt.8 -* usr/man/man8/ipcrm.8 -* usr/man/man8/ipcs.8 -* usr/man/man8/kbdrate.8 -* usr/man/man8/lpcntl.8 -* usr/man/man8/mkfs.minix.8 -* usr/man/man8/mkswap.8 -* usr/man/man8/mount.8 -* usr/man/man8/ramsize.8 -* usr/man/man8/rdev.8 -* usr/man/man8/reboot.8 -* usr/man/man8/renice.8 -* usr/man/man8/rootflags.8 -* usr/man/man8/setfdprm.8 -* usr/man/man8/setserial.8 -* usr/man/man8/setsid.8 -* usr/man/man8/shutdown.8 -* usr/man/man8/simpleinit.8 -* usr/man/man8/swapdev.8 -* usr/man/man8/swapoff.8 -* usr/man/man8/swapon.8 -* usr/man/man8/sync.8 -* usr/man/man8/syslogd.8 -* usr/man/man8/tunelp.8 -* usr/man/man8/umount.8 -* usr/man/man8/update_state.8 -* usr/man/man8/vidmode.8 -* usr/man/man8/vipw.8 -* usr/man/man8/zdump.8 -* usr/man/man8/zic.8 -* usr/sbin/chroot -* usr/sbin/ctrlaltdel -* usr/sbin/frag -* usr/sbin/syslogd -* usr/sbin/update_state -* usr/sbin/vipw -* usr/sbin/zdump -* usr/sbin/zic diff --git a/util-linux-2.1.lsm b/util-linux-2.1.lsm deleted file mode 100644 index a3c8d51f..00000000 --- a/util-linux-2.1.lsm +++ /dev/null @@ -1,23 +0,0 @@ -Begin3 -Title: util-linux: Miscellaneous utilities for Linux -Version: 2.1 -Entered-date: Thu Feb 16 09:23:18 1995 -Description: reboot shutdown simpleinit sln swapoff swapon cal chfn chsh - clear col colcrt colrm column dnsdomainname domainname - dsplit fdformat getopt hexdump hostid hostname ipcrm ipcs - last logger look lpcntl mcookie md5sum mesg namei newgrp - passwd ramsize rdev readprofile renice reset rev rootflags - script selection setfdprm setsid setterm strings swapdev - tsort tunelp ul vidmode wall whereis write chroot - ctrlaltdel frag syslogd update_state vipw zdump zic -Keywords: essential utilities -Author: several -Maintained-by: faith@cs.unc.edu (Rik Faith) -Primary-site: ftp.cs.unc.edu /pub/users/faith/linux - 640k util-linux-2.1.tar.gz - 570k util-linux-2.1.bin.tar.gz -Alternate-site: tsx-11.mit.edu /pub/linux/packages/utils -Alternate-site: sunsite.unc.edu /pub/Linux/system/Misc -Platforms: Linux 1.1.8x, GNU tar -Copying-policy: GPL, BSD, others -End diff --git a/version.h b/version.h index 030f8497..4b8deb07 100644 --- a/version.h +++ b/version.h @@ -1,2 +1,3 @@ -#define UTIL_LINUX 1 -char *util_linux_version="util-linux 2.8"; +#define UTIL_LINUX_VERSION "2.9i" + +const char * const util_linux_version = "util-linux " UTIL_LINUX_VERSION; -- 2.39.5