From: Karel Zak Date: Wed, 6 Dec 2006 23:25:39 +0000 (+0100) Subject: Imported from util-linux-2.9v tarball. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7eda085c41faa3445b4b168ce78ab18dab87d98a;p=util-linux Imported from util-linux-2.9v tarball. --- diff --git a/ANNOUNCE b/ANNOUNCE deleted file mode 100644 index 1eed25ef..00000000 --- a/ANNOUNCE +++ /dev/null @@ -1,32 +0,0 @@ -util-linux-2.9.tar.gz (source only distribution) - -READ the README file and the stuff below. - -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. -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. - - Util-linux is attempting to be portable, but the only platform it -has been tested much on is linux/intel. There have however been -integrated several patches for Arm, m68k, and Alpha linux versions. -The present version is known to compile on at least Linux 1.2/libc 4 -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.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 - -Andries Brouwer - diff --git a/HISTORY b/HISTORY index f0ccc9ab..c51c018e 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,82 @@ +util-linux 2.9v: + +* cfdisk no longer believes the kernel's HDGETGEO + (and may be able to partition a 2 TB disk) + +util-linux 2.9u: + +* Czech more.help and messages (Jiøí Pavlovský) +* Japanese messages (Daisuke Yamashita) +* fdisk fix (Klaus G. Wagner) +* mount fix (Hirokazu Takahashi) +* agetty: enable hardware flow control (Thorsten Kranzkowski) +* minor cfdisk improvements +* fdisk no longer accepts a default device +* Makefile fix + +util-linux 2.9t: + +* national language support for hwclock +* Japanese messages (both by Daisuke Yamashita) +* German messages and some misc i18n fixes (Elrond) +* Czech messages (Jiøí Pavlovský) +* wall fixed for /dev/pts/xx ttys +* make last and wall use getutent() (Sascha Schumann) + [Maybe this is bad: last reading all of wtmp may be too slow. + Revert in case people complain.] +* documented UUID= and LABEL= in fstab.5 +* added some partition types +* swapon: warn only if verbose + +util-linux 2.9s: + +* tunelp patch (Andrea Arcangeli) +* German messages (Elrond) + +util-linux 2.9[pqr]: + +* errno->errsv patch (Arnaldo Carvalho de Melo) +* hwclock patch for the Award 4.50g BIOS "2094" bug. (Dave Coffin) +* fdisk patch to correct deletion of last logical partition + +util-linux 2.9o: + +* fix to login by Ambrose C. Li +* improvement to mcookie inspired by a patch from Rik Faith +* more i18n by Arnaldo Carvalho de Melo; pt_BR locale + +util-linux 2.9n: + +* Added -u option to logger (write to user-specified socket; Martin Schultze) +* Added mount.smb script contributed by Greg Galperin +* Some more national language support +* mkfs.minix argument parsing fixed +* write fixed for /dev/pts/xx ttys +* configure adapted for the case of that needs u_char. + +util-linux 2.9m: + +* Added national language support (misiek@misiek.eu.org) +* minor improvements in mount, fdisk, cfdisk, agetty, more + +util-linux 2.9l: + +* Added /dev/port use to hwclock again - it may be necessary for Jensen. + +util-linux 2.9k: + +* major reshuffle of hwclock stuff; added sparc and alpha code +* tiny shutdown fix +* tiny fdisk fix + +util-linux 2.9j: + +* added configure +* merged three lists of partition types in *fdisk +* multi page display in cfdisk +* test for getlogin() == ""; +* start fixup hwclock + util-linux 2.9i: * fixed 2.9h typo in more @@ -90,6 +169,11 @@ HIGHLIGHTS for version 2.9: 0xF) Send questions and/or patches to util-linux@math.uio.no +util-linux 2.9 was released by Andries Brouwer - aeb@cwi.nl +The address util-linux@math.uio.no reaches Rik, Andries, Peter, +Michael, Erik, Nicolai and possibly others. Hwclock stuff is +forwarded to Bryan. + util-linux 2.8: HIGHLIGHTS for version 2.8: diff --git a/INSTALL b/INSTALL index c6a463e8..631d50f0 100644 --- a/INSTALL +++ b/INSTALL @@ -21,29 +21,32 @@ WARNING: The simpleinit and some other programs in this package are 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 +2) Untar util-linux-2.9X.tar.gz somewhere +3) cd util-linux-2.9X 4) Edit MCONFIG -5) make -6) make install -7) If you want to use simpleinit and agetty, then make softlinks from +5) ./configure +6) Look at defines.h and make_include, and edit if necessary +7) make +8) make install +9) 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: +If you have compilation problems: tell util-linux@math.uio.no about it. -- 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. +Users of libc 5.4.46 may get warnings like + /usr/include/linux/byteorder/swab.h:100: warning: no previous prototype for `__fswab16' +that they'll have to ignore. The Linux kernel includes are not meant to be included +in user programs, but libc5 does precisely that and is inherently broken. -elsewhere: tell util-linux@math.uio.no about it. +Some old libc have complaints like + /usr/include/sys/syslog.h:71: warning: missing braces around initializer +Also this is a libc/include problem. + +There should be no compilation errors. If you have runtime problems: diff --git a/LSM b/LSM deleted file mode 100644 index 41edbbf3..00000000 --- a/LSM +++ /dev/null @@ -1,26 +0,0 @@ -Begin3 -Title: util-linux: Miscellaneous utilities for Linux -Version: 2.9g -Description: agetty arch cal cfdisk chfn chkdupexe chsh - clear hwclock col colcrt colrm column ctrlaltdel - 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 - swapdev swapoff swapon tsort tunelp ul umount - vidmode vipw wall whereis write - -Keywords: essential utilities -Author: several -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 -Platforms: Linux 1.2.x/1.3.x/2.x/Libc 4/5/6, all CPUs -Copying-policy: GPL, BSD, others -End diff --git a/MAINTAINERS b/MAINTAINERS deleted file mode 100644 index 623b7788..00000000 --- a/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -util-linux is maintained by a group of people -(Rik, Andries, Peter, Michael, Erik, Nicolai), -all reachable at util-linux@math.uio.no. - -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 147fc1ae..58112ddf 100644 --- a/MCONFIG +++ b/MCONFIG @@ -10,8 +10,8 @@ # 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=yes +# define where is locale directrory (default /usr/share/locale) +LOCALEDIR=/usr/share/locale # If HAVE_PAM is set to "yes", then login, chfn, chsh, and newgrp # will use PAM for authentication. Additionally, passwd will not be @@ -65,9 +65,6 @@ HAVE_GETTY=no # properly.] USE_TTY_GROUP=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=yes @@ -81,12 +78,12 @@ CC= gcc # Different optimizations for different cpus. ifeq "$(CPU)" "intel" - OPT= -pipe -O3 -m486 -fomit-frame-pointer + OPT= -pipe -O2 -m486 -fomit-frame-pointer else ifeq "$(CPU)" "arm" OPT= -O2 -m3 -fomit-frame-pointer else - OPT= -O3 -fomit-frame-pointer + OPT= -O2 -fomit-frame-pointer endif endif @@ -103,23 +100,8 @@ CFLAGS = $(OPT) -I. -I$(LIB) $(WARNFLAGS) \ -DSBINDIR=\"$(SBINDIR)\" \ -DUSRSBINDIR=\"$(USRSBINDIR)\" \ -DLOGDIR=\"$(LOGDIR)\" \ - -DVARPATH=\"$(VARPATH)\" - -# Set HAVE_NCURSES to "yes" if you have ncurses -# (without it, more, ul and setterm are not made) -HAVE_NCURSES=yes - -# ncurses appears to be installed in three major ways. -# -# There is a subdirectory /usr/include/ncurses, with curses.h in -# CURSESFLAGS=-I/usr/include/ncurses -DNCH=0 -# No such subdirectory, but ncurses/curses.h is installed as ncurses.h -# CURSESFLAGS=-DNCH=1 -# No such subdirectory - is the ncurses one. -# CURSESFLAGS=-DNCH=0 -# Pick your choice. -CURSESFLAGS=-I/usr/include/ncurses -DNCH=0 -LIBCURSES=-lncurses + -DVARPATH=\"$(VARPATH)\" \ + -DLOCALEDIR=\"$(LOCALEDIR)\" # Set HAVE_SLANG to yes if you have slang (and prefer to use that for cfdisk) # (If neither HAVE_NCURSES nor HAVE_SLANG is defined, cfdisk is not made.) @@ -131,6 +113,7 @@ LIBCURSES=-lncurses # (no extra definition required). LIBSLANG=-lslang + DEVDIR= $(DESTDIR)/dev ETCDIR= $(DESTDIR)/etc SBINDIR= $(DESTDIR)/sbin diff --git a/Makefile b/Makefile index 92c9cae5..09571b2c 100644 --- a/Makefile +++ b/Makefile @@ -7,25 +7,32 @@ VERSION=2.9 +include ./make_include include ./MCONFIG -SUBDIRS=lib \ - getopt-1.0.3a \ +SUBDIRS=po \ + lib \ + getopt-1.0.3b \ disk-utils \ games \ login-utils \ misc-utils \ mount \ fdisk \ + clock \ sys-utils \ - text-utils + text-utils \ + kbd .PHONEY: all install clean -all: +all: defines.h @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done +defines.h make_include: + ./configure + install: @if [ "`whoami`" = "root" ]; then umask 022; fi @for subdir in $(SUBDIRS); do \ @@ -33,11 +40,15 @@ install: done clean: - -rm -f *.o *~ core poe.diffs + -rm -f *.o *~ omake conftest conftest.c core @for subdir in $(SUBDIRS); do \ (cd $$subdir && $(MAKE) $@) || exit 1; \ done +distclean: make_include clean + cd po && make distclean + -rm -f defines.h make_include + dist: (cd /tmp; \ rm -rf /tmp/util-linux-$(VERSION); \ diff --git a/README.clock b/README.clock new file mode 100644 index 00000000..a8cc98aa --- /dev/null +++ b/README.clock @@ -0,0 +1,39 @@ +Util-linux has always had the clock program (by Charles Hedrick, +Rob Hooft, Harald Koenig, Alan Modra). + +Slackware still uses the clock.c and clock.8 from util-linux-2.6 +(and calls the resulting source fragment clock-1.6.tar.gz). + +Bryan Henderson rewrote it, calling the result hwclock, +and util-linux-2.6 has both clock.c and hwclock.c, +util-linux-2.7 and later only have hwclock.c. + +Unfortunately, hwclock.c was broken in various ways, especially +on non-intel hardware, and distributions started shipping private +versions (usually derived from the old clock). + +For util-linux-2.9k Andries Brouwer took all clock versions around, +and merged them. The resulting hwclock program works on all architectures. +There are some kernel bugs in the handling of /dev/rtc on some i386 hardware, +so under certain circumstances where hwclock fails one has to give it the +--directisa flag to let hwclock do the clock access itself (which works) +rather than leave it to the kernel. [The precise cause is still being +investigated.] +This is the code presently found in the clock subdirectory. + +Bryan Henderson took this code again and merged it with his original +hwclock source. That is the code found in the util-linux-2.9q clock +directory. Unfortunately, this new version didnt work on Sparcs +and in util-linux-2.9r this code was moved to the clockB subdirectory. + + +Executive summary: +clock/hwclock is claimed to be good (but may need the --directisa flag). + + +Comments, bug reports etc are welcome. +Note that the source contains a rather detailed description of the clock +hardware involved. Additions and corrections are welcome. + +Andries +aeb@cwi.nl diff --git a/clock/Makefile b/clock/Makefile new file mode 100644 index 00000000..fd0522b3 --- /dev/null +++ b/clock/Makefile @@ -0,0 +1,29 @@ +# Makefile -- Makefile for util-linux Linux utilities +# +include ../make_include +include ../MCONFIG + +# Where to put man pages? + +MAN8= hwclock.8 + +# Where to put binaries? +# See the "install" rule for the links. . . + +SBIN= hwclock + + +all: $(SBIN) + + +hwclock.o: hwclock.c shhopt.h +hwclock.o cmos.o rtc.o kd.o: clock.h +hwclock: hwclock.o shhopt.o cmos.o rtc.o kd.o + +install: all + $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR) + $(INSTALLBIN) $(SBIN) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +clean: + -rm -f *.o *~ core $(SBIN) diff --git a/clock/README.aeb b/clock/README.aeb new file mode 100644 index 00000000..3955f905 --- /dev/null +++ b/clock/README.aeb @@ -0,0 +1,9 @@ +This directory contains the hwclock stuff as fixed by me. +It should work on all architectures. + +Bryan has backported my changes to his original source, +so the present directory should be superfluous - +however, his code fails on my Sparc. +Will look at it later. + +Andries Brouwer - aeb@cwi.nl diff --git a/sys-utils/README.hwclock b/clock/README.hwclock similarity index 100% rename from sys-utils/README.hwclock rename to clock/README.hwclock diff --git a/sys-utils/README.shhopt-1.1 b/clock/README.shhopt-1.1 similarity index 100% rename from sys-utils/README.shhopt-1.1 rename to clock/README.shhopt-1.1 diff --git a/clock/adjtime.patch b/clock/adjtime.patch new file mode 100644 index 00000000..81d0430f --- /dev/null +++ b/clock/adjtime.patch @@ -0,0 +1,302 @@ +From ao112@rgfn.epcc.edu Fri Mar 19 06:27:26 1999 +Received: from rgfn.epcc.edu (rgfn.epcc.edu [208.136.234.19]) by hera.cwi.nl with ESMTP + id GAA27711 for ; Fri, 19 Mar 1999 06:27:23 +0100 (MET) +Received: (from ao112@localhost) + by rgfn.epcc.edu (8.8.8/8.8.8) id WAA16797; + Thu, 18 Mar 1999 22:27:19 -0700 (MST) +Date: Thu, 18 Mar 1999 22:27:19 -0700 (MST) +Message-Id: <199903190527.WAA16797@rgfn.epcc.edu> +From: ao112@rgfn.epcc.edu (James P. Rutledge) +To: Andries.Brouwer@cwi.nl +Subject: Re: hwclock patch for drift_factor calculation improvement +Reply-To: ao112@rgfn.epcc.edu +Status: R + + + +> +>Could you perhaps make your patch relative to +>util-linux-2.9n (found in ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.9n.tar.gz) +>? +> +>(The hwclock stuff has changed quite a bit since 2.9g.) +> +>Andries +> + +Andries; + +Per your request, the patch has been modified for util-linux version +2.9n, from the version for 2.9g. + +The program "hwclock" (version 2.4c) could give more accurate +values for the drift factor that it places in the file "/etc/adjtime". + +A patch to improve the accuracy is included. + +I have incorporated some error sources which were not compensated +for into the drift factor calculation (performed when the "--set" +or the "--systohc" option is used) to make it more accurate. +In particular, the sync delay between the desired set time and the +start of the hardware clock second, and the expected drift since the +last hardware clock adjustment are now accounted for in the drift +factor calculation. + +With this patch, if at any time an adjust operation is attempted and +the hardware clock is found to be not valid, then the calibration +and adjustment time is set to zero to insure that if the hardware +clock should coincidentally return to validity, a calibration is not +done with bad history data (hardware clock info bad) and an adjust is +not attempted on bad (but now passing validity test) hardware clock +data. (With this patch, a previous calibration time of zero causes +the calibration time to initialize with the current time, when the +hardware clock is set, but no change is made to the drift factor, +so in effect, an initial calibration is started over while the previous +drift factor is retained.) + +Also, the behavior in the case of an initially missing "/etc/adjtime" +file or such a file produced by the predecessor "clock" program has +been slightly improved as follows: + + With this patch, if the file exists but was produced by "clock" + and, thus, is given a zero calibration time, the drift factor is + not updated upon the first calibration by "hwclock", but is left alone + and is only changed by subsequent calibrations. + + With this patch, if the file does not exist and, thus, is given + a zero calibration time, the drift factor is set to zero upon the + first calibration by "hwclock" and is then changed, as appropriate, by + subsequent calibrations. + + Also, with this patch, an "--adjust" operation against a non-existent + "/etc/adjtime" file or one which has zero as the last adjustment + time will not change the hardware clock setting. + +A context diff for a patch to the file "hwclock.c" in the directory +"util-linux-2.9n/clock" is appended. +To use the patch, "cd" to the directory "util-linux-2.9n/clock". +Run "patch < bug-report", where "bug-report" is the file name of +this mail message, to get new file "hwclock.c" which contains the proposed +new version. This patch is, of course, submitted per the GPL and the +appropriate "NO WARRANTY OF ANY KIND" and "USE AT YOUR OWN RISK" +disclaimers apply. + +Note that the patch presumptuously changes the "hwclock.c" version +number from 2.4c to 2.4c1 in "hwclock.c". + +Jim + +------------------ Patch file follows ---------------------------- +*** hwclock.c Thu Mar 18 22:04:01 1999 +--- new-hwclock.c Thu Mar 18 22:03:18 1999 +*************** +*** 76,86 **** + + #include "clock.h" + #include "../version.h" + + #define MYNAME "hwclock" +! #define VERSION "2.4c" + + char *progname = MYNAME; + + /* The struct that holds our hardware access routines */ + struct clock_ops *ur; +--- 76,86 ---- + + #include "clock.h" + #include "../version.h" + + #define MYNAME "hwclock" +! #define VERSION "2.4c1" + + char *progname = MYNAME; + + /* The struct that holds our hardware access routines */ + struct clock_ops *ur; +*************** +*** 581,601 **** + + + static void + adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, +! 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 + to . + +- We assume that the user has been doing regular drift adjustments +- using the drift factor in the adjtime file, so if and +- are different, that means the adjustment factor isn't +- quite right. +- + 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 +--- 581,598 ---- + + + static void + adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, +! const bool hclock_valid, +! const time_t hclocktime, +! const float sync_delay ) { + /*--------------------------------------------------------------------------- + Update the drift factor in <*adjtime_p> to reflect the fact that the + Hardware Clock was calibrated to and before that was set + to . + + 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 +*************** +*** 604,629 **** + ----------------------------------------------------------------------------*/ + 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)) +! * 24 * 60 * 60; + + if (debug) +! printf("Clock drifted %d seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n", +! (int) (nowtime - hclocktime), +! (int) (hclocktime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } +--- 601,642 ---- + ----------------------------------------------------------------------------*/ + if (!hclock_valid) { + if (debug) + printf("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n"); ++ } else if (adjtime_p->last_calib_time == 0) { ++ if (debug) ++ printf("Not adjusting drift factor because last calibration " ++ "time is zero,\nso history is bad and calibration startover " ++ "is necessary.\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 sec_per_day = 24.0 * 60.0 * 60.0; +! float atime_per_htime; /* adjusted time units per hardware time unit */ +! float adj_days; /* days since last adjustment (in hardware clock time) */ +! float cal_days; /* days since last calibration (in hardware clock time) */ +! float exp_drift; /* expected drift (sec) since last adjustment */ +! float unc_drift; /* uncorrected drift (sec) since last calibration */ +! float factor_adjust; /* amount to add to previous drift factor */ +! atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day; +! adj_days = (float)(hclocktime - adjtime_p->last_adj_time) / sec_per_day; +! exp_drift = adj_days * adjtime_p->drift_factor + adjtime_p->not_adjusted; +! unc_drift = (float)(nowtime - hclocktime) + sync_delay - exp_drift; +! cal_days = ((float)(adjtime_p->last_adj_time - adjtime_p->last_calib_time) +! + adjtime_p->not_adjusted) / (sec_per_day * atime_per_htime) +! + adj_days; +! factor_adjust = unc_drift / cal_days; + + if (debug) +! printf("Clock drifted %.1f seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n", +! unc_drift, +! (int) (nowtime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } +*************** +*** 764,773 **** +--- 777,794 ---- + + ----------------------------------------------------------------------------*/ + if (!hclock_valid) { + fprintf(stderr, "The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n"); ++ adjtime_p->last_calib_time = 0; /* calibration startover is required */ ++ adjtime_p->last_adj_time = 0; ++ adjtime_p->not_adjusted = 0; ++ adjtime_p->dirty = TRUE; ++ } else if (adjtime_p->last_adj_time == 0) { ++ if (debug) ++ printf("Not setting clock because last adjustment time is zero, " ++ "so history is bad."); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ + float retro; + /* Fraction of second we have to remove from clock after inserting +*************** +*** 878,888 **** + time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + universal, testing); +! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; +--- 899,910 ---- + time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + universal, testing); +! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime, +! time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; +*************** +*** 898,908 **** + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, +! hclocktime); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode_p = 1; +--- 920,930 ---- + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, +! hclocktime, (float)(read_time.tv_usec / 1E6)); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode_p = 1; + diff --git a/clock/clock.h b/clock/clock.h new file mode 100644 index 00000000..b57b499c --- /dev/null +++ b/clock/clock.h @@ -0,0 +1,33 @@ +#include +#include +#include /* for errno, EPERM, EINVAL, ENOENT */ +#include + +struct clock_ops { + char *interface_name; + int (*get_permissions)(void); + int (*read_hardware_clock)(struct tm *tm); + int (*set_hardware_clock)(const struct tm *tm); + int (*synchronize_to_clock_tick)(void); +}; + +extern struct clock_ops *probe_for_cmos_clock(void); +extern struct clock_ops *probe_for_rtc_clock(void); +extern struct clock_ops *probe_for_kd_clock(void); + +typedef int bool; +#define TRUE 1 +#define FALSE 0 + +/* hwclock.c */ +extern char *progname; +extern int debug; +extern void outsyserr(char *msg); + +/* cmos.c */ +extern void set_cmos_epoch(int ARCconsole, int SRM); +extern void set_cmos_access(int Jensen, int funky_toy); + +/* rtc.c */ +extern int get_epoch_rtc(unsigned long *epoch, int silent); +extern int set_epoch_rtc(unsigned long epoch); diff --git a/clock/cmos.c b/clock/cmos.c new file mode 100644 index 00000000..78d5dbb9 --- /dev/null +++ b/clock/cmos.c @@ -0,0 +1,598 @@ +/* + * i386 CMOS starts out with 14 bytes clock data + * alpha has something similar, but with details + * depending on the machine type. + * + * byte 0: seconds (0-59) + * byte 2: minutes (0-59) + * byte 4: hours (0-23 in 24hr mode, + * 1-12 in 12hr mode, with high bit unset/set if am/pm) + * byte 6: weekday (1-7, Sunday=1) + * byte 7: day of the month (1-31) + * byte 8: month (1-12) + * byte 9: year (0-99) + * Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set + * The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set + * The clock is undefined (being updated) if bit 7 of byte 10 is set. + * The clock is frozen (to be updated) by setting bit 7 of byte 11 + * Bit 7 of byte 14 indicates whether the CMOS clock is reliable: + * it is 1 if RTC power has been good since this bit was last read; + * it is 0 when the battery is dead and system power has been off. + * + * Avoid setting the RTC clock within 2 seconds of the day rollover + * that starts a new month or enters daylight saving time. + * + * The century situation is messy: + * Usually byte 50 (0x32) gives the century (in BCD, so 19 or 20 hex), + * but IBM PS/2 has (part of) a checksum there and uses byte 55 (0x37). + * Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 gives the century. + * The original RTC will not access any century byte; some modern + * versions will. If a modern RTC or BIOS increments the century byte + * it may go from 0x19 to 0x20, but in some buggy cases 0x1a is produced. + */ + +/* + * A struct tm has int fields + * tm_sec (0-59, 60 or 61 only for leap seconds) + * tm_min (0-59) + * tm_hour (0-23) + * tm_mday (1-31) + * tm_mon (0-11) + * tm_year (number of years since 1900) + * tm_wday (0-6, 0=Sunday) + * tm_yday (0-365) + * tm_isdst (>0: yes, 0: no, <0: unknown) + */ + +#include /* for geteuid() */ +#include /* for O_RDWR */ + +#include "nls.h" + +#if defined(__i386__) || defined(__alpha__) +#include /* for inb, outb */ +#else +void outb(int a, int b){} +int inb(int c){ return 0; } +#endif + +#include "clock.h" + +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) + +#define TM_EPOCH 1900 +int cmos_epoch = 1900; /* 1980 for an alpha in ARC console time */ + /* One also sees 1952 (Digital Unix?) + and 1958 (ALPHA_PRE_V1_2_SRM_CONSOLE) */ + +/* Martin Ostermann writes: +The problem with the Jensen is twofold: First, it has the clock at a +different address. Secondly, it has a distinction beween "local" and +normal bus addresses. The local ones pertain to the hardware integrated +into the chipset, like serial/parallel ports and of course, the RTC. +Those need to be addressed differently. This is handled fine in the kernel, +and it's not a problem, since this usually gets totally optimized by the +compile. But the i/o routines of (g)libc lack this support so far. +The result of this is, that the old clock program worked only on the +Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb +functions. + */ +int use_dev_port = 0; /* 1 for Jensen */ +int dev_port_fd; +unsigned short clock_ctl_addr = 0x70; /* 0x170 for Jensen */ +unsigned short clock_data_addr = 0x71; /* 0x171 for Jensen */ + + +int century_byte = 0; /* 0: don't access a century byte + 50 (0x32): usual PC value + 55 (0x37): PS/2 */ + +#ifdef __alpha__ +int funkyTOY = 0; /* 1 for PC164/LX164/SX164 type alpha */ +#endif + +#ifdef __alpha + +static int +is_in_cpuinfo(char *fmt, char *str) +{ + FILE *cpuinfo; + char field[256]; + char format[256]; + int found = 0; + + sprintf(format, "%s : %s", fmt, "%255s"); + + if ((cpuinfo = fopen ("/proc/cpuinfo", "r")) != NULL) { + while (!feof(cpuinfo)) { + if (fscanf (cpuinfo, format, field) == 1) { + if (strncmp(field, str, strlen(str)) == 0) + found = 1; + break; + } + fgets (field, 256, cpuinfo); + } + fclose(cpuinfo); + } + return found; +} + +/* Set cmos_epoch, either from user options, or by asking the kernel, + or by looking at /proc/cpu_info */ +void +set_cmos_epoch(int ARCconsole, int SRM) { + unsigned long epoch; + + /* Believe the user */ + if (ARCconsole) + cmos_epoch = 1980; + + if (ARCconsole || SRM) + return; + + + /* If we can ask the kernel, we don't need guessing from /proc/cpuinfo */ + if (get_epoch_rtc(&epoch, 1) == 0) { + cmos_epoch = epoch; + return; + } + + + /* See whether we are dealing with SRM or MILO, as they have + different "epoch" ideas. */ + if (is_in_cpuinfo("system serial number", "MILO")) { + ARCconsole = 1; + if (debug) printf (_("booted from MILO\n")); + } + + /* See whether we are dealing with a RUFFIAN aka UX, as they have REALLY + different TOY (TimeOfYear) format: BCD, and not an ARC-style epoch. + BCD is detected dynamically, but we must NOT adjust like ARC. */ + if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) { + ARCconsole = 0; + if (debug) printf (_("Ruffian BCD clock\n")); + } + + if (ARCconsole) + cmos_epoch = 1980; +} + +void +set_cmos_access(int Jensen, int funky_toy) { + + /* See whether we're dealing with a Jensen---it has a weird I/O + system. DEC was just learning how to build Alpha PCs. */ + if (Jensen || is_in_cpuinfo("system type", "Jensen")) { + use_dev_port = 1; + clock_ctl_addr = 0x170; + clock_data_addr = 0x171; + if (debug) printf (_("clockport adjusted to 0x%x\n"), clock_ctl_addr); + } + + /* see whether we are dealing with PC164/LX164/SX164, as they have a TOY + that must be accessed differently to work correctly. */ + if (funky_toy || + is_in_cpuinfo("system variation", "PC164") || + is_in_cpuinfo("system variation", "LX164") || + is_in_cpuinfo("system variation", "SX164")) { + funkyTOY = 1; + if (debug) printf (_("funky TOY!\n")); + } +} +#endif + + + + +#ifdef __i386__ + +/* + * Try to do CMOS access atomically, so that no other processes + * can get a time slice while we are reading or setting the clock. + * (Also, if the kernel time is synchronized with an external source, + * the kernel itself will fiddle with the RTC every 11 minutes.) + */ + +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + unsigned long v; + __asm__ volatile ("cli"); + v = (*op)(arg); + __asm__ volatile ("sti"); + return v; +} + +#elif __alpha__ + +/* + * The Alpha doesn't allow user-level code to disable interrupts (for + * good reasons). Instead, we ensure atomic operation by performing + * the operation and checking whether the high 32 bits of the cycle + * counter changed. If they did, a context switch must have occurred + * and we redo the operation. As long as the operation is reasonably + * short, it will complete atomically, eventually. + */ + +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + unsigned long ts1, ts2, n, v; + + for (n = 0; n < 1000; ++n) { + asm volatile ("rpcc %0" : "r="(ts1)); + v = (*op)(arg); + asm volatile ("rpcc %0" : "r="(ts2)); + + if ((ts1 ^ ts2) >> 32 == 0) { + return v; + } + } + fprintf(stderr, _("%s: atomic %s failed for 1000 iterations!"), progname, name); + exit(1); +} + +#else + +/* + * Hmmh, this isn't very atomic. Maybe we should force an error + * instead? + */ +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + return (*op)(arg); +} + +#endif + + +static inline +unsigned long cmos_read(unsigned long reg) +{ + if (use_dev_port) { + unsigned char v = reg | 0x80; + lseek(dev_port_fd, clock_ctl_addr, 0); + write(dev_port_fd, &v, 1); + lseek(dev_port_fd, clock_data_addr, 0); + read(dev_port_fd, &v, 1); + return v; + } else { + /* We only want to read CMOS data, but unfortunately + writing to bit 7 disables (1) or enables (0) NMI; + since this bit is read-only we have to guess the old status. + Various docs suggest that one should disable NMI while + reading/writing CMOS data, and enable it again afterwards. + This would yield the sequence + outb (reg | 0x80, 0x70); + val = inb(0x71); + outb (0x0d, 0x70); // 0x0d: random read-only location + Other docs state that "any write to 0x70 should be followed + by an action to 0x71 or the RTC wil be left in an unknown state". + Most docs say that it doesnt matter at all what one does. + */ + /* bit 0x80: disable NMI while reading - should we? + Let us follow the kernel and not disable. + Called only with 0 <= reg < 128 */ + outb (reg, clock_ctl_addr); + return inb (clock_data_addr); + } +} + +static inline +unsigned long cmos_write(unsigned long reg, unsigned long val) +{ + if (use_dev_port) { + unsigned char v = reg | 0x80; + lseek(dev_port_fd, clock_ctl_addr, 0); + write(dev_port_fd, &v, 1); + v = (val & 0xff); + lseek(dev_port_fd, clock_data_addr, 0); + write(dev_port_fd, &v, 1); + } else { + outb (reg, clock_ctl_addr); + outb (val, clock_data_addr); + } + return 0; +} + +unsigned long cmos_set_time(unsigned long arg) +{ + unsigned char save_control, save_freq_select, pmbit = 0; + struct tm tm = *(struct tm *) arg; + unsigned int century; + +/* + * CMOS byte 10 (clock status register A) has 3 bitfields: + * bit 7: 1 if data invalid, update in progress (read-only bit) + * (this is raised 224 us before the actual update starts) + * 6-4 select base frequency + * 010: 32768 Hz time base (default) + * 111: reset + * all other combinations are manufacturer-dependent + * (e.g.: DS1287: 010 = start oscillator, anything else = stop) + * 3-0 rate selection bits for interrupt + * 0000 none (may stop RTC) + * 0001, 0010 give same frequency as 1000, 1001 + * 0011 122 microseconds (minimum, 8192 Hz) + * .... each increase by 1 halves the frequency, doubles the period + * 1111 500 milliseconds (maximum, 2 Hz) + * 0110 976.562 microseconds (default 1024 Hz) + */ + + save_control = cmos_read (11); /* tell the clock it's being set */ + cmos_write (11, (save_control | 0x80)); + save_freq_select = cmos_read (10); /* stop and reset prescaler */ + cmos_write (10, (save_freq_select | 0x70)); + + tm.tm_year += TM_EPOCH; + century = tm.tm_year/100; + tm.tm_year -= cmos_epoch; + tm.tm_year %= 100; + tm.tm_mon += 1; + tm.tm_wday += 1; + + if (!(save_control & 0x02)) { /* 12hr mode; the default is 24hr mode */ + if (tm.tm_hour == 0) + tm.tm_hour = 24; + if (tm.tm_hour > 12) { + tm.tm_hour -= 12; + pmbit = 0x80; + } + } + + if (!(save_control & 0x04)) { /* BCD mode - the default */ + BIN_TO_BCD(tm.tm_sec); + BIN_TO_BCD(tm.tm_min); + BIN_TO_BCD(tm.tm_hour); + BIN_TO_BCD(tm.tm_wday); + BIN_TO_BCD(tm.tm_mday); + BIN_TO_BCD(tm.tm_mon); + BIN_TO_BCD(tm.tm_year); + BIN_TO_BCD(century); + } + + cmos_write (0, tm.tm_sec); + cmos_write (2, tm.tm_min); + cmos_write (4, tm.tm_hour | pmbit); + cmos_write (6, tm.tm_wday); + cmos_write (7, tm.tm_mday); + cmos_write (8, tm.tm_mon); + cmos_write (9, tm.tm_year); + if (century_byte) + cmos_write (century_byte, century); + + + /* The kernel sources, linux/arch/i386/kernel/time.c, have the + following comment: + + The following flags have to be released exactly in this order, + otherwise the DS12887 (popular MC146818A clone with integrated + battery and quartz) will not reset the oscillator and will not + update precisely 500 ms later. You won't find this mentioned + in the Dallas Semiconductor data sheets, but who believes data + sheets anyway ... -- Markus Kuhn + */ + + cmos_write (11, save_control); + cmos_write (10, save_freq_select); + return 0; +} + +static int +hclock_read(unsigned long reg) { + return atomic("clock read", cmos_read, (reg)); +} + +static void +hclock_set_time(const struct tm *tm) { + atomic("set time", cmos_set_time, (unsigned long)(tm)); +} + +static inline int +cmos_clock_busy() { + return +#ifdef __alpha__ + /* poll bit 4 (UF) of Control Register C */ + funkyTOY ? (hclock_read(12) & 0x10) : +#endif + /* poll bit 7 (UIP) of Control Register A */ + (hclock_read(10) & 0x80); +} + + +static int +synchronize_to_clock_tick_cmos(void) { + int i; + + /* Wait for rise. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + for (i = 0; !cmos_clock_busy(); i++) + if (i >= 10000000) + return 1; + + /* Wait for fall. Should be within 2.228 ms. */ + for (i = 0; cmos_clock_busy(); i++) + if (i >= 1000000) + return 1; + return 0; +} + + + +static int +read_hardware_clock_cmos(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via argument. + Assume we have an ISA machine and read the clock directly with CPU I/O + instructions. + + This function is not totally reliable. It takes a finite and + unpredictable amount of time to execute the code below. During that + time, the clock may change and we may even read an invalid value in + the middle of an update. We do a few checks to minimize this + possibility, but only the kernel can actually read the clock + properly, since it can execute code in a short and predictable + amount of time (by turning of interrupts). + + In practice, the chance of this function returning the wrong time is + extremely remote. + +-----------------------------------------------------------------------------*/ + bool got_time = FALSE; + unsigned char status, pmbit; + + status = pmbit = 0; /* just for gcc */ + + while (!got_time) { + /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress + (UIP) bit, which is on while and 244 uS before the Hardware Clock + updates itself. It updates the counters individually, so reading + them during an update would produce garbage. The update takes 2mS, + so we could be spinning here that long waiting for this bit to turn + off. + + Furthermore, it is pathologically possible for us to be in this + code so long that even if the UIP bit is not on at first, the + clock has changed while we were running. We check for that too, + and if it happens, we start over. + */ + + if (!cmos_clock_busy()) { + /* No clock update in progress, go ahead and read */ + tm->tm_sec = hclock_read(0); + tm->tm_min = hclock_read(2); + tm->tm_hour = hclock_read(4); + tm->tm_wday = hclock_read(6); + tm->tm_mday = hclock_read(7); + tm->tm_mon = hclock_read(8); + tm->tm_year = hclock_read(9); + status = hclock_read(11); +#if 0 + if (century_byte) + century = hclock_read(century_byte); +#endif + + /* Unless the clock changed while we were reading, consider this + a good clock read . + */ + if (tm->tm_sec == hclock_read (0)) + got_time = TRUE; + } + /* Yes, in theory we could have been running for 60 seconds and + the above test wouldn't work! + */ + } + + if (!(status & 0x04)) { /* BCD mode - the default */ + BCD_TO_BIN(tm->tm_sec); + BCD_TO_BIN(tm->tm_min); + pmbit = (tm->tm_hour & 0x80); + tm->tm_hour &= 0x7f; + BCD_TO_BIN(tm->tm_hour); + BCD_TO_BIN(tm->tm_wday); + BCD_TO_BIN(tm->tm_mday); + BCD_TO_BIN(tm->tm_mon); + BCD_TO_BIN(tm->tm_year); +#if 0 + BCD_TO_BIN(century); +#endif + } + + /* We don't use the century byte of the Hardware Clock + since we don't know its address (usually 50 or 55). + Here, we follow the advice of the X/Open Base Working Group: + "if century is not specified, then values in the range [69-99] + refer to years in the twentieth century (1969 to 1999 inclusive), + and values in the range [00-68] refer to years in the twenty-first + century (2000 to 2068 inclusive)." + */ + + tm->tm_wday -= 1; + tm->tm_mon -= 1; + tm->tm_year += (cmos_epoch - TM_EPOCH); + if (tm->tm_year < 69) + tm->tm_year += 100; + if (pmbit) { + tm->tm_hour += 12; + if (tm->tm_hour == 24) + tm->tm_hour = 0; + } + + tm->tm_isdst = -1; /* don't know whether it's daylight */ + return 0; +} + + + +static int +set_hardware_clock_cmos(const struct tm *new_broken_time) { + + hclock_set_time(new_broken_time); + return 0; +} + +static int +i386_iopl(const int level) { +#if defined(__i386__) || defined(__alpha__) + extern int iopl(const int level); + return iopl(level); +#else + return -2; +#endif +} + +static int +get_permissions_cmos(void) { + int rc; + + if (use_dev_port) { + if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) { + int errsv = errno; + fprintf(stderr, _("Cannot open /dev/port: %s"), strerror(errsv)); + rc = 1; + } else + rc = 0; + } else { + rc = i386_iopl(3); + if (rc == -2) { + fprintf(stderr, _("I failed to get permission because I didnt try.\n")); + } else if (rc != 0) { + rc = errno; + fprintf(stderr, _("%s is unable to get I/O port access: " + "the iopl(3) call failed.\n"), progname); + if(rc == EPERM && geteuid()) + fprintf(stderr, _("Probably you need root privileges.\n")); + } + } + return rc ? 1 : 0; +} + +static struct clock_ops cmos = { + "direct I/O instructions to ISA clock", + get_permissions_cmos, + read_hardware_clock_cmos, + set_hardware_clock_cmos, + synchronize_to_clock_tick_cmos, +}; + + +/* return &cmos if cmos clock present, NULL otherwise */ +/* choose this construction to avoid gcc messages about unused variables */ + +struct clock_ops * +probe_for_cmos_clock(void){ + int have_cmos = +#if defined(__i386__) || defined(__alpha__) + TRUE; +#else + FALSE; +#endif + return have_cmos ? &cmos : NULL; +} diff --git a/sys-utils/hwclock.8 b/clock/hwclock.8 similarity index 61% rename from sys-utils/hwclock.8 rename to clock/hwclock.8 index 58f4a259..0a216840 100644 --- a/sys-utils/hwclock.8 +++ b/clock/hwclock.8 @@ -20,12 +20,16 @@ clock \- query and set the hardware clock (RTC) .PP other options: .PP -.B "--utc --directisa --test --debug" +.B "--utc --localtime --directisa --test --debug" +.PP +and arcane options for DEC Alpha: +.PP +.B "--arc --jensen --srm --funky-toy" .PP Minimum unique abbreviations of all options are acceptable. .PP -Also, equivalent options -r, -w, -s, -a, -v, -u, and -D are accepted for -compatibility with the program "clock". +Also, equivalent options -r, -w, -s, -a, -v, -u, -D, -A, -J, -S, and -F +are accepted for compatibility with the program "clock". .SH DESCRIPTION .I hwclock @@ -48,6 +52,11 @@ what function to perform: .TP .B \-\-show Read the Hardware Clock and print the time on Standard Output. +The time is always in local time, even if you keep your Hardware Clock +in Coordinated Universal Time. See the +.B \-\-utc +option. + .TP .B \-\-set Set the Hardware Clock to the time given by the @@ -58,8 +67,11 @@ option. 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 TZ environment variable and/or +.IR /usr/lib/zoneinfo , +as +.BR 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. @@ -108,6 +120,12 @@ option is an argument to the program. For example, .sp .I hwclock --set --date="9/22/96 16:45:05" +.sp +The argument is in local time, even if you keep your Hardware Clock in +Coordinated Universal time. See the +.I \-\-utc +option. + .TP .B \-\-epoch=year Specifies the year which is the beginning of the Hardware Clock's @@ -122,28 +140,40 @@ For example, The following options apply to most functions. .TP .B \-\-utc +.TP +.B \-\-localtime Indicates that the Hardware Clock is kept in Coordinated Universal -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. +Time or local time, respectively. 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 +.IR hwclock . -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 +If you specify the wrong one of these options (or specify neither and +take a wrong default), both setting and querying of the Hardware Clock +will be messed up. + +If you specify neither +.B \-\-utc +nor +.B \-\-localtime +, the default is whichever was specified the last time .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. +was used to set the clock (i.e. hwclock was successfully run with the +.B \-\-set +, +.B \-\-systohc +, +or +.B \-\-adjust +options), as recorded in the adjtime file. If the adjtime file doesn't +exist, the default is local time. + .TP .B \-\-directisa -is meaningful only on an ISA machine. For all other machines, it has -no effect. This option tells +is meaningful only on an ISA machine or an Alpha (which implements enough +of ISA to be, roughly speaking, an ISA machine for +.IR hwclock 's +purposes). For other machines, it has no effect. This option tells .I hwclock to use explicit I/O instructions to access the Hardware Clock. Without this option, @@ -153,6 +183,93 @@ rtc device driver). If it is unable to open the device (for read), it will use the explicit I/O instructions anyway. The rtc device driver was new in Linux Release 2. +.TP +.B \-\-badyear +Indicates that the Hardware Clock is incapable of storing years outside +the range 1994-1999. There is a problem in some BIOSes (almost all +Award BIOSes made between 4/26/94 and 5/31/95) wherein they are unable +to deal with years after 1999. If one attempts to set the year-of-century +value to something less than 94 (or 95 in some cases), the value that +actually gets set is 94 (or 95). Thus, if you have one of these machines, +.I hwclock +cannot set the year after 1999 and cannot use the value of the clock as +the true time in the normal way. + +To compensate for this (without your getting a BIOS update, which would +definitely be preferable), always use +.B \-\-badyear +if you have one of these machines. When +.I hwclock +knows it's working with a brain-damaged clock, it ignores the year part of +the Hardware Clock value and instead tries to guess the year based on the +last calibrated date in the adjtime file, by assuming that that date is +within the past year. For this to work, you had better do a +.I hwclock \-\-set +or +.I hwclock \-\-systohc +at least once a year! + +Though +.I hwclock +ignores the year value when it reads the Hardware Clock, it sets the +year value when it sets the clock. It sets it to 1995, 1996, 1997, or +1998, whichever one has the same position in the leap year cycle as +the true year. That way, the Hardware Clock inserts leap days where +they belong. Again, if you let the Hardware Clock run for more than a +year without setting it, this scheme could be defeated and you could +end up losing a day. + +.I hwclock +warns you that you probably need +.B \-\-badyear +whenever it finds your Hardware Clock set to 1994 or 1995. + +.TP +.B \-\-srm +.TP +.B \-\-arc +.TP +.B \-\-jensen +.TP +.B \-\-funky\-toy +These options all tell +.I hwclock +what kind of Alpha machine you have. They +are invalid if you don't have an Alpha and shouldn't be necessary if you +do, because +.I hwclock +should be able to determine by itself what it's +running on. These options make it possible for +.I hwclock +to work even when +its environment does not conform to its expectations and thus it cannot +accurately determine what sort of system it is running on. If you think +hwclock is incorrectly determining the system's characteristics, try +running with the +.B \-\-debug +option to see what conclusions the program is +reaching and how. If you find you need one of these options to make +.I hwclock +work, contact the +.I hwclock +maintainer to see if the program can be improved to detect your system +automatically. + +.B \-\-jensen +means you are running on a Jensen model. + +.B \-\-arc +means your machine is running with ARC console time. + +.B \-\-srm +means your machine is running with SRM console time. + +.B \-\-funky\-toy +means that on your machine, one has to use the UF bit instead +of the UIP bit in the Hardware Clock to detect a time transition. "Toy" +in the option name refers to the Time Of Year facility of the machine. + + .TP .B \-\-test Do everything except actually updating the Hardware Clock or anything @@ -208,12 +325,12 @@ for which ISA was designed, the Hardware Clock is the only real time clock. .PP It is important that the System Time not have any discontinuities such as would happen if you used the -.I date(1L) +.BR date (1L) program to set it while the system is running. You can, however, do whatever you want to the Hardware Clock while the system is running, and the next 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) +.BR 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. @@ -244,104 +361,93 @@ users of the timezone value would actually compute the wrong local time. .PP Therefore, -.I -hwclock +.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 +.I hwclock simply adds an hour to the geographical part. .SH How hwclock Accesses the Hardware Clock .PP -.I -hwclock +.I hwclock Uses many different ways to get and set Hardware Clock values. The most normal way is to do I/O to the device special file /dev/rtc, which is presumed to be driven by the rtc device driver. However, this method is not always available. For one thing, the rtc driver is a relatively recent addition to Linux. Older systems don't have it. +Also, though there are versions of the rtc driver that work on DEC +Alphas, there appear to be plenty of Alphas on which the rtc driver +does not work (a common symptom is hwclock hanging). .PP On older systems, the method of accessing the Hardware Clock depends on the system hardware. .PP On an ISA system, -.I -hwclock -can directly access the "CMOS memory" registers that constitute the clock, -by doing I/O to Ports 0x70 and 0x71. It can only do this if running with -superuser effective userid. +.I hwclock +can directly access the "CMOS memory" registers that +constitute the clock, by doing I/O to Ports 0x70 and 0x71. It does +this with actual I/O instructions and consequently can only do it if +running with superuser effective userid. (In the case of a Jensen +Alpha, there is no way for +.I hwclock +to execute those I/O instructions, and so it uses instead the +/dev/port device special file, which provides almost as low-level an +interface to the I/O subsystem). This is a really poor method of accessing the clock, for all the reasons that user space programs are generally not supposed to do direct I/O and disable interrupts. Hwclock provides it because it is -the only method available with older Linux kernels for ISA machines. +the only method available on ISA and Alpha systems which don't have +working rtc device drivers available. .PP On an m68k system, -.I -hwclock +.I hwclock can access the clock via the console driver, via the device special file /dev/tty1. .PP -On an Alpha, -.I -/dev/rtc -is the only choice. - -There are or were some Alpha Linux systems that don't have /dev/rtc -and there are or were programs that accessed the clock via almost -direct I/O using /dev/port. However, this is not as good a method as -/dev/rtc and such programs were not widely enough used that hwclock -has any need to be backward compatible with them. So hwclock does not -provide the /dev/port method and consequently will not work on an -Alpha that doesn't have /dev/rtc. - -.PP -.I -hwclock +.I hwclock tries to use /dev/rtc. If it is compiled for a kernel that doesn't have that function or it is unable to open /dev/rtc, -.I -hwclock -will fall back to another method, if available. On an ISA +.I hwclock +will fall back to another method, if available. On an ISA or Alpha machine, you can force -.I -hwclock +.I hwclock to use the direct manipulation of the CMOS registers without even trying -/dev/rtc by specifying the --directisa option. +.I /dev/rtc +by specifying the \-\-directisa option. .SH The Adjust Function .PP The Hardware Clock is usually not very accurate. However, much of its -inaccuracy is completely predictable -- it gains or loses the same amount +inaccuracy is completely predictable - it gains or loses the same amount of time every day. This is called systematic drift. -.I Hwclock's +.IR hwclock 's "adjust" function lets you make systematic corrections to correct the systematic drift. .PP It works like this: -.I Hwclock +.I hwclock keeps a file, .I /etc/adjtime, that keeps some historical information. This is called the adjtime file. .PP Suppose you start with no adjtime file. You issue a -.I hwclock --set +.I hwclock \-\-set command to set the Hardware Clock to the true current time. .I Hwclock creates the adjtime file and records in it the current time as the last time the clock was calibrated. 5 days later, the clock has gained 10 seconds, so you issue another -.I hwclock --set +.I hwclock \-\-set command to set it back 10 seconds. .I Hwclock updates the adjtime file to show the current time as the last time the clock was calibrated, and records 2 seconds per day as the systematic drift rate. 24 hours go by, and then you issue a -.I hwclock --adjust +.I hwclock \-\-adjust command. .I Hwclock consults the adjtime file and sees that the clock gains 2 seconds per @@ -349,15 +455,15 @@ day when left alone and that it has been left alone for exactly one day. So it subtracts 2 seconds from the Hardware Clock. It then records the current time as the last time the clock was adjusted. Another 24 hours goes by and you issue another -.I hwclock --adjust. +.I hwclock \-\-adjust. .I Hwclock 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 (using -.I --set +.I \-\-set or -.I --systohc +.I \-\-systohc ), .I hwclock recalculates the systematic drift rate based on how long it has been @@ -374,23 +480,36 @@ the accumulated drift will be more than a second and will do the adjustment then. .PP It is good to do a -.I hwclock --adjust +.I hwclock \-\-adjust just before the -.I hwclock --hctosys +.I hwclock \-\-hctosys at system startup time, and maybe periodically while the system is running via cron. .PP +The adjtime file, while named for its historical purpose of controlling +adjustments only, actually contains other information for use by hwclock +in remembering information from one invocation to the next. +.PP The format of the adjtime file is, in ASCII: .PP 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 -). +.IR clock ) +as a decimal integer. .PP Line 2: 1 number: Resulting number of seconds since 1969 UTC of most -recent calibration. +recent calibration. Zero if there has been no calibration yet or it +is known that any previous calibration is moot (for example, because +the Hardware Clock has been found, since that calibration, not to +contain a valid time). This is a decimal integer. +.PP +Line 3: "UTC" or "LOCAL". Tells whether the Hardware Clock is set to +Coordinated Universal Time or local time. You can always override this +value with options on the +.I hwclock +command line. .PP You can use an adjtime file that was previously used with the .I clock @@ -398,7 +517,7 @@ program with .I hwclock. -.SH Automatic Hardware Clock Synchronization By the Kernel +.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 @@ -411,41 +530,70 @@ 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. +.IR "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 +.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 +.I hwclock \-\-adjust or -.I hwclock --hctosys . +.IR "hwclock \-\-hctosys" . You'll just make a mess. It is acceptable to use a -.I hwclock --hctosys +.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 +.SH ISA Hardware Clock Century value + +There is some sort of standard that defines CMOS memory Byte 50 on an ISA +machine as an indicator of what century it is. +.I hwclock +does not use or set that byte because there are some machines that +don't define the byte that way, and it really isn't necessary anyway, +since the year-of-century does a good job of implying which century it +is. + +If you have a bona fide use for a CMOS century byte, contact the +.I hwclock +maintainer; an option may be appropriate. + +Note that this section is only relevant when you are using the "direct +ISA" method of accessing the Hardware Clock. + + + +.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), -tzset(3) +.I /dev/rtc +.I /dev/port +.I /dev/tty1 +.I /proc/cpuinfo + +.SH "SEE ALSO" +.BR adjtimex (8), +.BR date (1), +.BR gettimeofday (2), +.BR settimeofday (2), +.BR crontab (1), +.BR tzset (3) .SH AUTHORS Written By Bryan Henderson, September 1996 (bryanh@giraffe-data.com), 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. +program by Charles Hedrick, Rob Hooft, and Harald Koenig. +See the source code for complete history and credits. + + diff --git a/clock/hwclock.c b/clock/hwclock.c new file mode 100644 index 00000000..a496e057 --- /dev/null +++ b/clock/hwclock.c @@ -0,0 +1,1290 @@ +/* + * hwclock.c + * + * clock.c was written by Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 + * Modified for clock adjustments - Rob Hooft , Nov 1992 + * Improvements by Harald Koenig + * and Alan Modra . + * + * Major rewrite by Bryan Henderson , 96.09.19. + * The new program is called hwclock. New features: + * - You can set the hardware clock without also modifying the system clock. + * - You can read and set the clock with finer than 1 second precision. + * - When you set the clock, hwclock automatically refigures the drift + * rate, based on how far off the clock was before you set it. + * + * Reshuffled things, added sparc code, and re-added alpha stuff + * by David Mosberger + * and Jay Estabrook + * and Martin Ostermann , aeb@cwi.nl, 990212. + * + * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98 + */ + +/* + * clock [-u] -r - read hardware clock + * clock [-u] -w - write hardware clock from system time + * clock [-u] -s - set system time from hardware clock + * clock [-u] -a - set system time from hardware clock, adjust the time + * to correct for systematic error, and write it back to + * the hardware clock + * -u indicates cmos clock is kept in universal time + * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980) + * -J indicates we're dealing with a Jensen (early DEC Alpha PC) + */ + +/* + * Explanation of `adjusting' (Rob Hooft): + * + * The problem with my machine is that its CMOS clock is 10 seconds + * per day slow. With this version of clock.c, and my '/etc/rc.local' + * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error + * is automatically corrected at every boot. + * + * To do this job, the program reads and writes the file '/etc/adjtime' + * to determine the correction, and to save its data. In this file are + * three numbers: + * + * 1) the correction in seconds per day. (So if your clock runs 5 + * seconds per day fast, the first number should read -5.0) + * 2) the number of seconds since 1/1/1970 the last time the program + * was used + * 3) the remaining part of a second which was leftover after the last + * adjustment + * + * Installation and use of this program: + * + * a) create a file '/etc/adjtime' containing as the first and only line: + * '0.0 0 0.0' + * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in + * universal or local time. This updates the second number. + * c) set your system time using the 'date' command. + * d) update your cmos time using 'clock -wu' or 'clock -w' + * e) replace the first number in /etc/adjtime by your correction. + * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clock.h" +#include "../version.h" +#include "nls.h" + +#define MYNAME "hwclock" +#define VERSION "2.4c" + +char *progname = MYNAME; + +/* The struct that holds our hardware access routines */ +struct clock_ops *ur; + +#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); + +/* Here the information for time adjustments is kept. */ +#define ADJPATH "/etc/adjtime" + +/* Store the date here when "badyear" flag is set. */ +#define LASTDATE "/var/lib/lastdate" + +struct adjtime { + /* This is information we keep in the adjtime file that tells us how + to do drift corrections. Elements are all straight from the + adjtime file, so see documentation of that file for details. + Exception is , which is an indication that what's in this + structure is not what's in the disk file (because it has been + updated since read from the disk file). + */ + bool dirty; + float drift_factor; + time_t last_adj_time; + float not_adjusted; + time_t last_calib_time; +}; + +bool debug; + /* We are running in debug mode, wherein we put a lot of information about + what we're doing to standard output. */ + +bool badyear; + /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ + +/* + * Almost all Award BIOS's made between 04/26/94 and 05/31/95 + * have a nasty bug limiting the RTC year byte to the range 94-99. + * Any year between 2000 and 2093 gets changed to 2094, every time + * you start the system. + * With the --badyear option, we write the date to file and hope + * that the file is updated at least once a year. + * I recommend putting this command "hwclock --badyear" in the monthly + * crontab, just to be safe. -- Dave Coffin 11/12/98 + */ +void +write_date_to_file (struct tm *tm) { + FILE *fp; + + if ((fp = fopen(LASTDATE,"w"))) { + fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1, + tm->tm_year+1900); + fclose(fp); + } else + perror(LASTDATE); +} + +void +read_date_from_file (struct tm *tm) { + int last_mday, last_mon, last_year; + FILE *fp; + + if ((fp = fopen(LASTDATE,"r"))) { + if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) { + tm->tm_year = last_year-1900; + if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday) + tm->tm_year ++; + } + fclose(fp); + } + write_date_to_file (tm); +} + +static float +time_diff(struct timeval subtrahend, struct timeval subtractor) { +/*--------------------------------------------------------------------------- + The difference in seconds between two times in "timeval" format. +----------------------------------------------------------------------------*/ + return( (subtrahend.tv_sec - subtractor.tv_sec) + + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 ); +} + + +static struct timeval +time_inc(struct timeval addend, float increment) { +/*---------------------------------------------------------------------------- + The time, in "timeval" format, which is seconds after + the time . Of course, may be negative. +-----------------------------------------------------------------------------*/ + struct timeval newtime; + + newtime.tv_sec = addend.tv_sec + (int) increment; + newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6; + + /* Now adjust it so that the microsecond value is between 0 and 1 million */ + if (newtime.tv_usec < 0) { + newtime.tv_usec += 1E6; + newtime.tv_sec -= 1; + } else if (newtime.tv_usec >= 1E6) { + newtime.tv_usec -= 1E6; + newtime.tv_sec += 1; + } + return(newtime); +} + + + +static void +read_adjtime(struct adjtime *adjtime_p, int *rc_p) { +/*---------------------------------------------------------------------------- + Read the adjustment parameters out of the /etc/adjtime file. + + Return them as the adjtime structure <*adjtime_p>. + + If there is no /etc/adjtime file, return defaults. + If values are missing from the file, return defaults for them. + + return *rc_p = 0 if all OK, !=0 otherwise. + +-----------------------------------------------------------------------------*/ + FILE *adjfile; + int rc; /* local return code */ + struct stat statbuf; /* We don't even use the contents of this. */ + + rc = stat(ADJPATH, &statbuf); + if (rc < 0 && errno == ENOENT) { + /* He doesn't have a adjtime file, so we'll use defaults. */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + + *rc_p = 0; + } else { + adjfile = fopen(ADJPATH, "r"); /* open file for reading */ + if (adjfile == NULL) { + outsyserr("cannot open file " ADJPATH); + *rc_p = 2; + } else { + char line1[81]; /* String: first line of adjtime file */ + char line2[81]; /* String: second line of adjtime file */ + + line1[0] = '\0'; /* In case fgets fails */ + fgets(line1, sizeof(line1), adjfile); + line2[0] = '\0'; /* In case fgets fails */ + fgets(line2, sizeof(line2), adjfile); + + fclose(adjfile); + + /* Set defaults in case values are missing from file */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + + sscanf(line1, "%f %d %f", + &adjtime_p->drift_factor, + (int *) &adjtime_p->last_adj_time, + &adjtime_p->not_adjusted); + + sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time); + + *rc_p = 0; + } + adjtime_p->dirty = FALSE; + + if (debug) { + printf(_("Last drift adjustment done at %d seconds after 1969\n"), + (int) adjtime_p->last_adj_time); + printf(_("Last calibration done at %d seconds after 1969\n"), + (int) adjtime_p->last_calib_time); + } + } +} + + +static void +synchronize_to_clock_tick(int *retcode_p) { +/*----------------------------------------------------------------------------- + Wait until the falling edge of the Hardware Clock's update flag so + that any time that is read from the clock immediately after we + return will be exact. + + The clock only has 1 second precision, so it gives the exact time only + once per second, right on the falling edge of the update flag. + + We wait (up to one second) either blocked waiting for an rtc device + or in a CPU spin loop. The former is probably not very accurate. + + Return *retcode_p == 0 if it worked, nonzero if it didn't. + +-----------------------------------------------------------------------------*/ + if (debug) printf(_("Waiting for clock tick...\n")); + + *retcode_p = ur->synchronize_to_clock_tick(); + + if (debug) printf(_("...got clock tick\n")); +} + + + +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). 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 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 + local time zone input, we may have to fake it out by temporarily + changing the local time zone to UTC. + */ + zone = (char *) getenv("TZ"); /* remember original time zone */ + mktime_result = mktime(&tm); + if (universal) { + /* Set timezone to UTC */ + setenv("TZ", "", TRUE); + /* Note: tzset() gets called implicitly by the time code, but only the + first time. When changing the environment variable, better call + tzset() explicitly. + */ + tzset(); + } + 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(); +} + + +static void +read_hardware_clock(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; + int err; + + err = ur->read_hardware_clock(&tm); + + if (badyear) + read_date_from_file(&tm); + + if (debug) + printf (_("Time read from Hardware Clock: %02d:%02d:%02d\n"), + tm.tm_hour, tm.tm_min, tm.tm_sec); + mktime_tz(tm, universal, valid_p, systime_p); +} + + +static void +set_hardware_clock(const time_t newtime, + const bool universal, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time , in local time zone or UTC, + according to . +----------------------------------------------------------------------------*/ + int err; + struct tm new_broken_time; + /* Time to which we will set Hardware Clock, in broken down format, in + the time zone of caller's choice + */ + + if (universal) + new_broken_time = *gmtime(&newtime); + else + new_broken_time = *localtime(&newtime); + + if (debug) + printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d " + "= %d seconds since 1969\n"), + new_broken_time.tm_hour, new_broken_time.tm_min, + new_broken_time.tm_sec, (int) newtime); + + if (testing) + printf(_("Clock not changed - testing only.\n")); + else { + if (badyear) { + /* + * Write the real year to a file, then write a fake year + * between 1995 and 1998 to the RTC. This way, Award BIOS boots + * on 29 Feb 2000 thinking that it's 29 Feb 1996. + */ + write_date_to_file (&new_broken_time); + new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3); + } + err = ur->set_hardware_clock(&new_broken_time); + } +} + + + +static void +set_hardware_clock_exact(const time_t settime, + const struct timeval ref_time, + const bool universal, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time "settime", in local time zone or UTC, + according to "universal". + + But correct "settime" and wait for a fraction of a second so that + "settime" is the value of the Hardware Clock as of system time + "ref_time", which is in the past. For example, if "settime" is + 14:03:05 and "ref_time" is 12:10:04.5 and the current system + time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since + "ref_time") and then set the Hardware Clock to 14:03:07, thus + getting a precise and retroactive setting of the clock. + + (Don't be confused by the fact that the system clock and the Hardware + Clock differ by two hours in the above example. That's just to remind + you that there are two independent time scales here). + + This function ought to be able to accept set times as fractional times. + Idea for future enhancement. + +-----------------------------------------------------------------------------*/ + time_t newtime; /* Time to which we will set Hardware Clock */ + struct timeval now_time; /* locally used time */ + + gettimeofday(&now_time, NULL); + newtime = settime + (int) time_diff(now_time, ref_time) + 1; + if (debug) + printf(_("Time elapsed since reference time has been %.6f seconds.\n" + "Delaying further to reach the next full second.\n"), + time_diff(now_time, ref_time)); + + /* Now delay some more until Hardware Clock time newtime arrives */ + do gettimeofday(&now_time, NULL); + while (time_diff(now_time, ref_time) < newtime - settime); + + set_hardware_clock(newtime, universal, testing); +} + + + +static void +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". +-----------------------------------------------------------------------------*/ + 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 */ + + /* 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)); + } +} + + + +static int +interpret_date_string(const char *date_opt, time_t * const time_p) { +/*---------------------------------------------------------------------------- + Interpret the value of the --date option, which is something like + "13:05:01". In fact, it can be any of the myriad ASCII strings that specify + a time which the "date" program can understand. The date option value in + question is our "dateopt" argument. + + The specified time is in the local time zone. + + Our output, "*time_p", is a seconds-into-epoch time. + + We use the "date" program to interpret the date string. "date" must be + runnable by issuing the command "date" to the /bin/sh shell. That means + in must be in the current PATH. + + If anything goes wrong (and many things can), we return return code + 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p + is valid. +----------------------------------------------------------------------------*/ + FILE *date_child_fp; + char date_resp[100]; + const char magic[]="seconds-into-epoch="; + char date_command[100]; + int retcode; /* our eventual return code */ + int rc; /* local return code */ + + if (date_opt == NULL) { + fprintf(stderr, _("No --date option specified.\n")); + retcode = 14; + } else if (strchr(date_opt, '"') != NULL) { + /* Quotation marks in date_opt would ruin the date command we construct. + */ + fprintf(stderr, _("The value of the --date option is not a valid date.\n" + "In particular, it contains quotation marks.\n")); + retcode = 12; + } else { + sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s", + date_opt); + if (debug) printf(_("Issuing date command: %s\n"), date_command); + + date_child_fp = popen(date_command, "r"); + if (date_child_fp == NULL) { + outsyserr(_("Unable to run 'date' program in /bin/sh shell. " + "popen() failed")); + retcode = 10; + } else { + date_resp[0] = '\0'; /* in case fgets fails */ + fgets(date_resp, sizeof(date_resp), date_child_fp); + if (debug) printf(_("response from date command = %s\n"), date_resp); + if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) { + fprintf(stderr, _("The date command issued by %s returned " + "unexpected results.\n" + "The command was:\n %s\nThe response was:\n %s\n"), + MYNAME, date_command, date_resp); + retcode = 8; + } else { + int seconds_since_epoch; + rc = sscanf(date_resp + sizeof(magic)-1, "%d", &seconds_since_epoch); + if (rc < 1) { + fprintf(stderr, _("The date command issued by %s returned" + "something other than an integer where the converted" + "time value was expected.\n" + "The command was:\n %s\nThe response was:\n %s\n"), + MYNAME, date_command, date_resp); + retcode = 6; + } else { + retcode = 0; + *time_p = seconds_since_epoch; + if (debug) + printf(_("date string %s equates to %d seconds since 1969.\n"), + date_opt, (int) *time_p); + } + } + fclose(date_child_fp); + } + } + return(retcode); +} + + + +static int +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. + + 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 */ + + 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 { + 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 ); + printf( _("\ttz.tz_minuteswest = %ld\n"), timezone/60 - 60*daylight); + } + 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 + outsyserr(_("settimeofday() failed")); + retcode = 1; + } else retcode = 0; + } + } + return(retcode); +} + + +static void +adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, + 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 + to . + + We assume that the user has been doing regular drift adjustments + using the drift factor in the adjtime file, so if and + are different, that means the adjustment factor isn't + quite right. + + 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 (!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)) + * 24 * 60 * 60; + + if (debug) + printf(_("Clock drifted %d seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n"), + (int) (nowtime - hclocktime), + (int) (hclocktime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } + adjtime_p->last_calib_time = nowtime; + + adjtime_p->last_adj_time = nowtime; + + adjtime_p->not_adjusted = 0; + + adjtime_p->dirty = TRUE; +} + + + +static void +calculate_adjustment( + const float factor, + const time_t last_time, + const float not_adjusted, + const time_t systime, + int *adjustment_p, + float *retro_p, + const int debug ) { +/*---------------------------------------------------------------------------- + Do the drift adjustment calculation. + + The way we have to set the clock, we need the adjustment in two parts: + + 1) an integer number of seconds (return as *adjustment_p) + + 2) a positive fraction of a second (less than 1) (return as *retro_p) + + The sum of these two values is the adjustment needed. Positive means to + advance the clock or insert seconds. Negative means to retard the clock + or remove seconds. +----------------------------------------------------------------------------*/ + float exact_adjustment; + + exact_adjustment = ((float) (systime - last_time)) * factor / (24 * 60 * 60) + + not_adjusted; + *adjustment_p = FLOOR(exact_adjustment); + + *retro_p = exact_adjustment - (float) *adjustment_p; + if (debug) { + printf (_("Time since last adjustment is %d seconds\n"), + (int) (systime - last_time)); + printf (_("Need to insert %d seconds and refer time back " + "%.6f seconds ago\n"), + *adjustment_p, *retro_p); + } +} + + + +static void +save_adjtime(const struct adjtime adjtime, const bool testing) { +/*----------------------------------------------------------------------------- + Write the contents of the structure to its disk file. + + But if the contents are clean (unchanged since read from disk), don't + bother. +-----------------------------------------------------------------------------*/ + char newfile[405]; /* Stuff to write to disk file */ + + if (adjtime.dirty) { + /* snprintf is not always available, but this is safe + as long as libc does not use more than 100 positions for %ld or %f */ + sprintf(newfile, "%f %ld %f\n%ld\n", + adjtime.drift_factor, + (long) adjtime.last_adj_time, + adjtime.not_adjusted, + (long) adjtime.last_calib_time ); + + if (testing) { + printf(_("Not updating adjtime file because of testing mode.\n")); + printf(_("Would have written the following to %s:\n%s"), + ADJPATH, newfile); + } else { + FILE *adjfile; + int err = 0; + + adjfile = fopen(ADJPATH, "w"); + if (adjfile == NULL) { + outsyserr("Could not open file with the clock adjustment parameters " + "in it (" ADJPATH ") for writing"); + err = 1; + } else { + if (fprintf(adjfile, newfile) < 0) { + outsyserr("Could not update file with the clock adjustment " + "parameters (" ADJPATH ") in it"); + err = 1; + } + if (fclose(adjfile) < 0) { + outsyserr("Could not update file with the clock adjustment " + "parameters (" ADJPATH ") in it"); + err = 1; + } + } + if (err) + fprintf(stderr, _("Drift adjustment parameters not updated.\n")); + } + } +} + + + +static void +do_adjustment(struct adjtime *adjtime_p, + const bool hclock_valid, const time_t hclocktime, + const struct timeval read_time, + const bool universal, const bool testing) { +/*--------------------------------------------------------------------------- + Do the adjustment requested, by 1) setting the Hardware Clock (if + 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. + + 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 + could be a short time ago). + + : the Hardware Clock is kept in UTC. + + : We are running in test mode (no updating of clock). + + We do not bother to update the clock if the adjustment would be less than + one second. This is to avoid cumulative error and needless CPU hogging + (remember we use an infinite loop for some timing) if the user runs us + frequently. + +----------------------------------------------------------------------------*/ + 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; + /* 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), + 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")); + } +} + + + +static void +determine_clock_access_method(const bool user_requests_ISA) { + + ur = NULL; + + if (user_requests_ISA) + ur = probe_for_cmos_clock(); + + if (!ur) + ur = probe_for_rtc_clock(); + + if (!ur) + ur = probe_for_kd_clock(); + + if (!ur && !user_requests_ISA) + ur = probe_for_cmos_clock(); + + if (debug) { + if (ur) + printf(_("Using %s.\n"), ur->interface_name); + else + printf(_("No usable clock interface found.\n")); + } +} + +static void +manipulate_clock(const bool show, const bool adjust, + const bool set, const time_t set_time, + const bool hctosys, const bool systohc, + const struct timeval startup_time, + const bool universal, const bool testing, + int *retcode_p + ) { +/*--------------------------------------------------------------------------- + Do all the normal work of hwclock - read, set clock, etc. + + Issue output to stdout and error message to stderr where appropriate. + + Return rc == 0 if everything went OK, rc != 0 if not. +----------------------------------------------------------------------------*/ + struct adjtime adjtime; + /* Contents of the adjtime file, or what they should be. */ + int rc; /* local return code */ + bool no_auth; /* User lacks necessary authorization to access the clock */ + + no_auth = ur->get_permissions(); + + if (no_auth) *retcode_p = 1; + else { + if (adjust || set || systohc) + read_adjtime(&adjtime, &rc); + else { + /* A little trick to avoid reading the file if we don't have to */ + adjtime.dirty = FALSE; + rc = 0; + } + if (rc != 0) *retcode_p = 2; + else { + synchronize_to_clock_tick(retcode_p); + /* this takes up to 1 second */ + if (*retcode_p == 0) { + 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(universal, &hclock_valid, &hclocktime); + + if (show) { + 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, + universal, testing); + adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; + } else if (systohc) { + struct timeval nowtime, reftime; + /* We can only set_hardware_clock_exact to a whole seconds + time, so we set it with reference to the most recent + whole seconds time. + */ + gettimeofday(&nowtime, NULL); + reftime.tv_sec = nowtime.tv_sec; + reftime.tv_usec = 0; + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, + hclocktime); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf(_("Unable to set system clock.\n")); + *retcode_p = 1; + } else *retcode_p = 0; + } + save_adjtime(adjtime, testing); + } + } + } +} + + +static void +manipulate_epoch(const bool getepoch, const bool setepoch, + const int epoch_opt, const bool testing) { +/*---------------------------------------------------------------------------- + Get or set the Hardware Clock epoch value in the kernel, as appropriate. + , , and are hwclock invocation options. + + == -1 if the user did not specify an "epoch" option. + +-----------------------------------------------------------------------------*/ + /* + Maintenance note: This should work on non-Alpha machines, but the + evidence today (98.03.04) indicates that the kernel only keeps the + epoch value on Alphas. If that is ever fixed, this function should be + changed. + */ + +#ifndef __alpha__ + fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock " + "only on an Alpha machine.\nThis copy of hwclock was built for " + "a machine other than Alpha\n(and thus is presumably not running " + "on an Alpha now). No action taken.\n")); +#else + if (getepoch) { + unsigned long epoch; + + if (get_epoch_rtc(&epoch, 0)) + fprintf(stderr, _("Unable to get the epoch value from the kernel.\n")); + else + printf(_("Kernel is assuming an epoch value of %lu\n"), epoch); + } else if (setepoch) { + if (epoch_opt == -1) + fprintf(stderr, _("To set the epoch value, you must use the 'epoch' " + "option to tell to what value to set it.\n")); + else if (testing) + printf(_("Not setting the epoch to %d - testing only.\n"), + epoch_opt); + else if (set_epoch_rtc(epoch_opt)) + printf(_("Unable to set the epoch value in the kernel.\n")); + } +#endif +} + +int +main(int argc, char **argv, char **envp) { + + struct timeval startup_time; + /* The time we started up, in seconds into the epoch, including fractions. + */ + time_t set_time; /* Time to which user said to set Hardware Clock */ + + bool permitted; /* User is permitted to do the function */ + int retcode; /* Our eventual return code */ + + int rc; /* local return code */ + + /* option_def is the control table for the option parser. These other + variables are the results of parsing the options and their meanings + are given by the option_def. The only exception is , which + may be modified after parsing is complete to effect an implied option. + */ + bool show, set, systohc, hctosys, adjust, getepoch, setepoch, version; + bool ARCconsole, universal, testing, directisa, Jensen, SRM, funky_toy; + char *date_opt; + int epoch_opt; + + const optStruct option_def[] = { + { 'r', (char *) "show", OPT_FLAG, &show, 0 }, + { 0, (char *) "set", OPT_FLAG, &set, 0 }, + { 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 }, + { 's', (char *) "hctosys", OPT_FLAG, &hctosys, 0 }, + { 0, (char *) "getepoch", OPT_FLAG, &getepoch, 0 }, + { 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 }, + { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 }, + { 'v', (char *) "version", OPT_FLAG, &version, 0 }, + { 0, (char *) "date", OPT_STRING, &date_opt, 0 }, + { 0, (char *) "epoch", OPT_UINT, &epoch_opt, 0 }, + { 'u', (char *) "utc", OPT_FLAG, &universal, 0 }, + { 0, (char *) "badyear", OPT_FLAG, &badyear, 0 }, + { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 }, + { 0, (char *) "test", OPT_FLAG, &testing, 0 }, + { 'D', (char *) "debug", OPT_FLAG, &debug, 0 }, +#ifdef __alpha__ + { 'A', (char *) "ARC", OPT_FLAG, &ARCconsole,0 }, + { 'J', (char *) "Jensen", OPT_FLAG, &Jensen, 0 }, + { 'S', (char *) "SRM", OPT_FLAG, &SRM, 0 }, + { 'F', (char *) "funky-toy", OPT_FLAG, &funky_toy, 0 }, +#endif + { 0, (char *) NULL, OPT_END, NULL, 0 } + }; + int argc_parse; /* argc, except we modify it as we parse */ + char **argv_parse; /* argv, except we modify it as we parse */ + + gettimeofday(&startup_time, NULL); /* Remember what time we were invoked */ + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* set option defaults */ + show = set = systohc = hctosys = adjust = getepoch = setepoch = + version = universal = ARCconsole = SRM = funky_toy = + directisa = badyear = Jensen = testing = debug = FALSE; + date_opt = NULL; + epoch_opt = -1; + + argc_parse = argc; argv_parse = argv; + optParseOptions(&argc_parse, argv_parse, option_def, 0); + /* Uses and sets argc_parse, argv_parse. + Sets show, systohc, hctosys, adjust, universal, version, testing, + debug, set, date_opt, getepoch, setepoch, epoch_opt + */ + /* This is an ugly routine - for example, if I give an incorrect + option, it only says "unrecognized option" without telling + me what options are recognized. Rewrite with standard + getopt() and usage() and throw shhopt out. */ + + if (argc_parse - 1 > 0) { + fprintf(stderr, _("%s takes no non-option arguments. " + "You supplied %d.\n"), + MYNAME, argc_parse - 1); + exit(100); + } + + if (show + set + systohc + hctosys + adjust + + getepoch + setepoch + version > 1) { + fprintf(stderr, _("You have specified multiple function options.\n" + "You can only perform one function at a time.\n")); + exit(100); + } + +#ifdef __alpha__ + set_cmos_epoch(ARCconsole, SRM); + set_cmos_access(Jensen, funky_toy); +#endif + + if (set) { + rc = interpret_date_string(date_opt, &set_time); /* (time-consuming) */ + if (rc != 0) { + fprintf(stderr, _("No usable set-to time. Cannot set clock.\n")); + exit(100); + } + } + + if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch | + version)) + show = 1; /* default to show */ + + + if (getuid() == 0) permitted = TRUE; + else { + /* program is designed to run setuid (in some situations) -- be secure! */ + if (set || hctosys || systohc || adjust) { + fprintf(stderr, + _("Sorry, only the superuser can change the Hardware Clock.\n")); + permitted = FALSE; + } else if (setepoch) { + fprintf(stderr, + _("Sorry, only the superuser can change " + "the Hardware Clock epoch in the kernel.\n")); + permitted = FALSE; + } else permitted = TRUE; + } + + if (!permitted) retcode = 2; + else { + retcode = 0; + if (version) { + printf(MYNAME " " VERSION "/%s\n",util_linux_version); + } else if (getepoch || setepoch) { + manipulate_epoch(getepoch, setepoch, epoch_opt, testing); + } else { + determine_clock_access_method(directisa); + if (!ur) + fprintf(stderr, _("Cannot access the Hardware Clock via any known " + "method. Use --debug option to see the details of our " + "search for an access method.\n")); + else + manipulate_clock(show, adjust, set, set_time, hctosys, systohc, + startup_time, universal, testing, &rc); + } + } + exit(retcode); +} + +/* A single routine for greater uniformity */ +void +outsyserr(char *msg) { + fprintf(stderr, _("%s: %s, errno=%d: %s.\n"), + progname, msg, errno, strerror(errno)); +} + +/**************************************************************************** + + 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. + + Fix some word length things so it works on Alpha. + + Make it work when /dev/rtc doesn't have the interrupt functions. + In this case, busywait for the top of a second instead of blocking and + waiting for the update complete interrupt. + + Fix a bunch of bugs too numerous to mention. + + 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte + 50) of the ISA Hardware Clock when using direct ISA I/O. Problem + discovered by job (jei@iclnl.icl.nl). + + Use the rtc clock access method in preference to the KDGHWCLK method. + Problem discovered by Andreas Schwab . + + November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt + (janl@math.uio.no) to make it compile on linux 1.2 machines as well + as more recent versions of the kernel. Introduced the NO_CLOCK + access method and wrote feature test code to detect absense of rtc + headers. + + +************************************************************************** + Maintenance notes + + To compile this, you must use GNU compiler optimization (-O option) + in order to make the "extern inline" functions from asm/io.h (inb(), + etc.) compile. If you don't optimize, which means the compiler + will generate no inline functions, the references to these functions + in this program will be compiled as external references. Since you + probably won't be linking with any functions by these names, you will + have unresolved external references when you link. + + The program is designed to run setuid superuser, since we need to be + able to do direct I/O. (More to the point: we need permission to + execute the iopl() system call). (However, if you use one of the + methods other than direct ISA I/O to access the clock, no setuid is + required). + + Here's some info on how we must deal with the time that elapses while + this program runs: There are two major delays as we run: + + 1) Waiting up to 1 second for a transition of the Hardware Clock so + we are synchronized to the Hardware Clock. + + 2) Running the "date" program to interpret the value of our --date + option. + + Reading the /etc/adjtime file is the next biggest source of delay and + uncertainty. + + The user wants to know what time it was at the moment he invoked us, + not some arbitrary time later. And in setting the clock, he is + giving us the time at the moment we are invoked, so if we set the + clock some time later, we have to add some time to that. + + So we check the system time as soon as we start up, then run "date" + and do file I/O if necessary, then wait to synchronize with a + Hardware Clock edge, then check the system time again to see how + much time we spent. We immediately read the clock then and (if + appropriate) report that time, and additionally, the delay we measured. + + If we're setting the clock to a time given by the user, we wait some + more so that the total delay is an integral number of seconds, then + set the Hardware Clock to the time the user requested plus that + integral number of seconds. N.B. The Hardware Clock can only be set + in integral seconds. + + If we're setting the clock to the system clock value, we wait for + the system clock to reach the top of a second, and then set the + Hardware Clock to the system clock's value. + + Here's an interesting point about setting the Hardware Clock: On my + machine, when you set it, it sets to that precise time. But one can + imagine another clock whose update oscillator marches on a steady one + second period, so updating the clock between any two oscillator ticks + is the same as updating it right at the earlier tick. To avoid any + complications that might cause, we set the clock as soon as possible + after an oscillator tick. + + + About synchronizing to the Hardware Clock when reading the time: The + precision of the Hardware Clock counters themselves is one second. + You can't read the counters and find out that is 12:01:02.5. But if + you consider the location in time of the counter's ticks as part of + its value, then its precision is as infinite as time is continuous! + What I'm saying is this: To find out the _exact_ time in the + hardware clock, we wait until the next clock tick (the next time the + second counter changes) and measure how long we had to wait. We + then read the value of the clock counters and subtract the wait time + and we know precisely what time it was when we set out to query the + time. + + hwclock uses this method, and considers the Hardware Clock to have + infinite precision. + + + Enhancements needed: + + - When waiting for whole second boundary in set_hardware_clock_exact, + fail if we miss the goal by more than .1 second, as could happen if + we get pre-empted (by the kernel dispatcher). + +****************************************************************************/ + diff --git a/clock/kd.c b/clock/kd.c new file mode 100644 index 00000000..9ec91f00 --- /dev/null +++ b/clock/kd.c @@ -0,0 +1,149 @@ +/* kd.c - KDGHWCLK stuff, possibly m68k only */ +#include /* for close() */ +#include /* for O_RDONLY */ +#include + +#include "clock.h" +#include "nls.h" + +static int con_fd = -1; /* opened by probe_for_kd_clock() */ + /* never closed */ + +/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */ +#include +#ifndef KDGHWCLK +#define KDGHWCLK 0x4B50 /* get hardware clock */ +#define KDSHWCLK 0x4B51 /* set hardware clock */ +struct hwclk_time { + unsigned sec; /* 0..59 */ + unsigned min; /* 0..59 */ + unsigned hour; /* 0..23 */ + unsigned day; /* 1..31 */ + unsigned mon; /* 0..11 */ + unsigned year; /* 70... */ + int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ +}; +#endif + +static int +synchronize_to_clock_tick_kd(void) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + int i; + + /* The time when we were called (and started waiting) */ + struct hwclk_time start_time, nowtime; + + if (debug) + printf(_("Waiting in loop for time from KDGHWCLK to change\n")); + + if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed")); + return 3; + } + + i = 0; + do { + if (i++ >= 1000000) { + fprintf(stderr, _("Timed out waiting for time change.\n")); + return 2; + } + if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed in loop")); + return 3; + } + } while (start_time.sec == nowtime.sec); + + return 0; +} + + +static int +read_hardware_clock_kd(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to /dev/tty1 on what we assume is an m68k + machine. + + Note that we don't use /dev/console here. That might be a serial + console. +-----------------------------------------------------------------------------*/ + struct hwclk_time t; + + if (ioctl(con_fd, KDGHWCLK, &t) == -1) { + outsyserr(_("ioctl() failed to read time from /dev/tty1")); + exit(5); + } + + tm->tm_sec = t.sec; + tm->tm_min = t.min; + tm->tm_hour = t.hour; + tm->tm_mday = t.day; + tm->tm_mon = t.mon; + tm->tm_year = t.year; + tm->tm_wday = t.wday; + tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */ + + return 0; +} + + +static int +set_hardware_clock_kd(const struct tm *new_broken_time) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time . Use ioctls to + /dev/tty1 on what we assume is an m68k machine. + + Note that we don't use /dev/console here. That might be a serial console. +----------------------------------------------------------------------------*/ + struct hwclk_time t; + + t.sec = new_broken_time->tm_sec; + t.min = new_broken_time->tm_min; + t.hour = new_broken_time->tm_hour; + t.day = new_broken_time->tm_mday; + t.mon = new_broken_time->tm_mon; + t.year = new_broken_time->tm_year; + t.wday = new_broken_time->tm_wday; + + if (ioctl(con_fd, KDSHWCLK, &t ) == -1) { + outsyserr(_("ioctl() to open /dev/tty1 failed")); + exit(1); + } + return 0; +} + +static int +get_permissions_kd(void) { + return 0; +} + +static struct clock_ops kd = { + "KDGHWCLK interface to m68k clock", + get_permissions_kd, + read_hardware_clock_kd, + set_hardware_clock_kd, + synchronize_to_clock_tick_kd, +}; + +/* return &kd if KDGHWCLK works, NULL otherwise */ +struct clock_ops * +probe_for_kd_clock() { + struct clock_ops *ret = NULL; + struct hwclk_time t; + + if (con_fd < 0) + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd >= 0) { + if (ioctl( con_fd, KDGHWCLK, &t ) == -1) { + if (errno != EINVAL) + outsyserr(_("KDGHWCLK ioctl failed")); + } else + ret = &kd; + } else { + outsyserr(_("Can't open /dev/tty1")); + } + return ret; +} diff --git a/clock/rtc.c b/clock/rtc.c new file mode 100644 index 00000000..65238843 --- /dev/null +++ b/clock/rtc.c @@ -0,0 +1,389 @@ +/* rtc.c - Use /dev/rtc for clock access */ +#include /* for close() */ +#include /* for O_RDONLY */ +#include + +#include "clock.h" +#include "nls.h" + +/* + * Get defines for rtc stuff. + * + * Getting the rtc defines is nontrivial. + * The obvious way is by including + * but that again includes which again includes ... + * and on sparc and alpha this gives compilation errors for + * many kernel versions. So, we give the defines ourselves here. + * Moreover, some Sparc person decided to be incompatible, and + * used a struct rtc_time different from that used in mc146818rtc.h. + */ + +/* On Sparcs, there is a that defines different ioctls + (that are required on my machine). However, this include file + does not exist on other architectures. */ +/* One might do: +#ifdef __sparc__ +#include +#endif + */ +/* The following is roughly equivalent */ +struct sparc_rtc_time +{ + int sec; /* Seconds (0-59) */ + int min; /* Minutes (0-59) */ + int hour; /* Hour (0-23) */ + int dow; /* Day of the week (1-7) */ + int dom; /* Day of the month (1-31) */ + int month; /* Month of year (1-12) */ + int year; /* Year (0-99) */ +}; + +#define RTCGET _IOR('p', 20, struct sparc_rtc_time) +#define RTCSET _IOW('p', 21, struct sparc_rtc_time) + + +/* non-sparc stuff */ +#if 0 +#include +/* Check if the /dev/rtc interface is available in this version of + the system headers. 131072 is linux 2.0.0. */ +#if LINUX_VERSION_CODE >= 131072 +#include +#endif +#endif + +/* struct rtc_time is present since 1.3.99 */ +/* Earlier (since 1.3.89), a struct tm was used. */ +struct linux_rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */ +#ifndef RTC_RD_TIME +#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) +#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ +#define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */ +#endif +/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */ +#ifndef RTC_EPOCH_READ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ +#endif + + +static int +do_rtc_read_ioctl(int rtc_fd, struct tm *tm) { + int rc; + char *ioctlname; +#ifdef __sparc__ + struct sparc_rtc_time stm; + + ioctlname = "RTCGET"; + rc = ioctl(rtc_fd, RTCGET, &stm); +#else + ioctlname = "RTC_RD_TIME"; + rc = ioctl(rtc_fd, RTC_RD_TIME, tm); +#endif + if (rc == -1) { + perror(ioctlname); + fprintf(stderr, _("ioctl() to /dev/rtc to read the time failed.\n")); + exit(5); + } +#ifdef __sparc__ + tm->tm_sec = stm.sec; + tm->tm_min = stm.min; + tm->tm_hour = stm.hour; + tm->tm_mday = stm.dom; + tm->tm_mon = stm.month - 1; + tm->tm_year = stm.year - 1900; + tm->tm_wday = stm.dow - 1; + tm->tm_yday = -1; /* day in the year */ +#endif + tm->tm_isdst = -1; /* don't know whether it's daylight */ + return 0; +} + + +static int +busywait_for_rtc_clock_tick(const int rtc_fd) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by reading /dev/rtc in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + struct tm start_time; + /* The time when we were called (and started waiting) */ + struct tm nowtime; + int i; /* local loop index */ + int rc; + + if (debug) + printf(_("Waiting in loop for time from /dev/rtc to change\n")); + + rc = do_rtc_read_ioctl(rtc_fd, &start_time); + if (rc) + return 1; + + /* Wait for change. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + for (i = 0; + (rc = do_rtc_read_ioctl(rtc_fd, &nowtime)) == 0 + && start_time.tm_sec == nowtime.tm_sec; + i++) + if (i >= 1000000) { + fprintf(stderr, _("Timed out waiting for time change.\n")); + return 2; + } + + if (rc) + return 3; + return 0; +} + + + +static int +synchronize_to_clock_tick_rtc(void) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for /dev/rtc. +-----------------------------------------------------------------------------*/ +int rtc_fd; /* File descriptor of /dev/rtc */ +int ret; + + rtc_fd = open("/dev/rtc",O_RDONLY); + if (rtc_fd == -1) { + outsyserr(_("open() of /dev/rtc failed")); + ret = 1; + } else { + int rc; /* Return code from ioctl */ + /* Turn on update interrupts (one per second) */ +#if defined(__alpha__) || defined(__sparc__) + /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */ + rc = -1; + errno = EINVAL; +#else + rc = ioctl(rtc_fd, RTC_UIE_ON, 0); +#endif + if (rc == -1 && errno == EINVAL) { + /* This rtc device doesn't have interrupt functions. This is typical + on an Alpha, where the Hardware Clock interrupts are used by the + kernel for the system clock, so aren't at the user's disposal. + */ + if (debug) printf(_("/dev/rtc does not have interrupt functions. ")); + ret = busywait_for_rtc_clock_tick(rtc_fd); + } else if (rc != -1) { + int rc; /* return code from ioctl */ + unsigned long dummy; + + /* this blocks until the next update interrupt */ + rc = read(rtc_fd, &dummy, sizeof(dummy)); + if (rc == -1) { + outsyserr(_("read() to /dev/rtc to wait for clock tick failed")); + ret = 1; + } else { + ret = 0; + } + /* Turn off update interrupts */ + rc = ioctl(rtc_fd, RTC_UIE_OFF, 0); + if (rc == -1) + outsyserr(_("ioctl() to /dev/rtc to turn off update interrupts " + "failed")); + } else { + outsyserr(_("ioctl() to /dev/rtc to turn on update interrupts " + "failed unexpectedly")); + ret = 1; + } + close(rtc_fd); + } + return ret; +} + + +static int +read_hardware_clock_rtc(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to "rtc" device /dev/rtc. +-----------------------------------------------------------------------------*/ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open("/dev/rtc",O_RDONLY); + if (rtc_fd == -1) { + outsyserr(_("open() of /dev/rtc failed")); + exit(5); + } + + /* Read the RTC time/date */ + do_rtc_read_ioctl(rtc_fd, tm); + + close(rtc_fd); + return 0; +} + + +static int +set_hardware_clock_rtc(const struct tm *new_broken_time) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the broken down time . + Use ioctls to "rtc" device /dev/rtc. +----------------------------------------------------------------------------*/ + int rc; + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + outsyserr(_("Unable to open /dev/rtc")); + exit(5); + } else { + char *ioctlname; +#ifdef __sparc__ + struct sparc_rtc_time stm; + + stm.sec = new_broken_time->tm_sec; + stm.min = new_broken_time->tm_min; + stm.hour = new_broken_time->tm_hour; + stm.dom = new_broken_time->tm_mday; + stm.month = new_broken_time->tm_mon + 1; + stm.year = new_broken_time->tm_year + 1900; + stm.dow = new_broken_time->tm_wday + 1; + + ioctlname = "RTCSET"; + rc = ioctl(rtc_fd, RTCSET, &stm); +#else + ioctlname = "RTC_SET_TIME"; + rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time); +#endif + if (rc == -1) { + perror(ioctlname); + fprintf(stderr, _("ioctl() to /dev/rtc to set the time failed.\n")); + exit(5); + } else { + if (debug) + printf(_("ioctl(%s) was successful.\n"), ioctlname); + } + close(rtc_fd); + } + return 0; +} + + +static int +get_permissions_rtc(void) { + return 0; +} + +static struct clock_ops rtc = { + "/dev/rtc interface to clock", + get_permissions_rtc, + read_hardware_clock_rtc, + set_hardware_clock_rtc, + synchronize_to_clock_tick_rtc, +}; + +/* return &rtc if /dev/rtc can be opened, NULL otherwise */ +struct clock_ops * +probe_for_rtc_clock(){ + int rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd > 0) { + close(rtc_fd); + return &rtc; + } + if (debug) + outsyserr(_("Open of /dev/rtc failed")); + return NULL; +} + + + +int +get_epoch_rtc(unsigned long *epoch_p, int silent) { +/*---------------------------------------------------------------------------- + Get the Hardware Clock epoch setting from the kernel. +----------------------------------------------------------------------------*/ + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + if (!silent) { + if (errno == ENOENT) + fprintf(stderr, _( + "To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file /dev/rtc. This file does not exist on this system.\n")); + else + outsyserr(_("Unable to open /dev/rtc")); + } + return 1; + } + + if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) { + if (!silent) + outsyserr(_("ioctl(RTC_EPOCH_READ) to /dev/rtc failed")); + close(rtc_fd); + return 1; + } + + if (debug) + printf(_("we have read epoch %ld from /dev/rtc " + "with RTC_EPOCH_READ ioctl.\n"), *epoch_p); + + close(rtc_fd); + return 0; +} + + + +int +set_epoch_rtc(unsigned long epoch) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock epoch in the kernel. +----------------------------------------------------------------------------*/ + int rtc_fd; + + if (epoch < 1900) { + /* kernel would not accept this epoch value */ + /* Hmm - bad habit, deciding not to do what the user asks + just because one believes that the kernel might not like it. */ + fprintf(stderr, _("The epoch value may not be less than 1900. " + "You requested %ld\n"), epoch); + return 1; + } + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + if (errno == ENOENT) + fprintf(stderr, _("To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file /dev/rtc. This file does not exist on this system.\n")); + else + outsyserr(_("Unable to open /dev/rtc")); + return 1; + } + + if (debug) + printf(_("setting epoch to %ld " + "with RTC_EPOCH_SET ioctl to /dev/rtc.\n"), epoch); + + if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) { + if (errno == EINVAL) + fprintf(stderr, _("The kernel device driver for /dev/rtc " + "does not have the RTC_EPOCH_SET ioctl.\n")); + else + outsyserr(_("ioctl(RTC_EPOCH_SET) to /dev/rtc failed")); + close(rtc_fd); + return 1; + } + + close(rtc_fd); + return 0; +} diff --git a/sys-utils/shhopt-1.1.lsm b/clock/shhopt-1.1.lsm similarity index 100% rename from sys-utils/shhopt-1.1.lsm rename to clock/shhopt-1.1.lsm diff --git a/clock/shhopt.c b/clock/shhopt.c new file mode 100644 index 00000000..e55a7293 --- /dev/null +++ b/clock/shhopt.c @@ -0,0 +1,468 @@ +/* $Id: shhopt.c,v 2.2 1997/07/06 23:11:55 aebr Exp $ */ +/************************************************************************** + * + * FILE shhopt.c + * + * DESCRIPTION Functions for parsing command line arguments. Values + * of miscellaneous types may be stored in variables, + * or passed to functions as specified. + * + * REQUIREMENTS Some systems lack the ANSI C -function strtoul. If your + * system is one of those, you'll ned to write one yourself, + * or get the GNU liberty-library (from prep.ai.mit.edu). + * + * WRITTEN BY Sverre H. Huseby + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "shhopt.h" +#include "nls.h" + +/************************************************************************** + * * + * P R I V A T E D A T A * + * * + **************************************************************************/ + +static void optFatalFunc(const char *, ...); +static void (*optFatal)(const char *format, ...) = optFatalFunc; + + + +/************************************************************************** + * * + * P R I V A T E F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optFatalFunc + * + * FUNCTION Show given message and abort the program. + * + * INPUT format, ... + * Arguments used as with printf(). + * + * RETURNS Never returns. The program is aborted. + * + */ +void optFatalFunc(const char *format, ...) +{ + va_list ap; + + fflush(stdout); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + exit(99); +} + + + +/*------------------------------------------------------------------------- + * + * NAME optStructCount + * + * FUNCTION Get number of options in a optStruct. + * + * INPUT opt array of possible options. + * + * RETURNS Number of options in the given array. + * + * DESCRIPTION Count elements in an optStruct-array. The strcture must + * be ended using an element of type OPT_END. + * + */ +static int optStructCount(const optStruct opt[]) +{ + int ret = 0; + + while (opt[ret].type != OPT_END) + ++ret; + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optMatch + * + * FUNCTION Find a matching option. + * + * INPUT opt array of possible options. + * s string to match, without `-' or `--'. + * lng match long option, otherwise short. + * + * RETURNS Index to the option if found, -1 if not found. + * + * DESCRIPTION Short options are matched from the first character in + * the given string. + * + */ +static int optMatch(const optStruct opt[], const char *s, int lng) +{ + int nopt, q, matchlen = 0; + char *p; + + nopt = optStructCount(opt); + if (lng) { + if ((p = strchr(s, '=')) != NULL) + matchlen = p - s; + else + matchlen = strlen(s); + } + for (q = 0; q < nopt; q++) { + if (lng) { + if (!opt[q].longName) + continue; + if (strncmp(s, opt[q].longName, matchlen) == 0) + return q; + } else { + if (!opt[q].shortName) + continue; + if (*s == opt[q].shortName) + return q; + } + } + return -1; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optString + * + * FUNCTION Return a (static) string with the option name. + * + * INPUT opt the option to stringify. + * lng is it a long option? + * + * RETURNS Pointer to static string. + * + */ +static char *optString(const optStruct *opt, int lng) +{ + static char ret[31]; + + if (lng) { + strcpy(ret, "--"); + strncpy(ret + 2, opt->longName, 28); + } else { + ret[0] = '-'; + ret[1] = opt->shortName; + ret[2] = '\0'; + } + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optNeedsArgument + * + * FUNCTION Check if an option requires an argument. + * + * INPUT opt the option to check. + * + * RETURNS Boolean value. + * + */ +static int optNeedsArgument(const optStruct *opt) +{ + return opt->type == OPT_STRING + || opt->type == OPT_INT + || opt->type == OPT_UINT + || opt->type == OPT_LONG + || opt->type == OPT_ULONG; +} + + + +/*------------------------------------------------------------------------- + * + * NAME argvRemove + * + * FUNCTION Remove an entry from an argv-array. + * + * INPUT argc pointer to number of options. + * argv array of option-/argument-strings. + * i index of option to remove. + * + * OUTPUT argc new argument count. + * argv array with given argument removed. + * + */ +static void argvRemove(int *argc, char *argv[], int i) +{ + if (i >= *argc) + return; + while (i++ < *argc) + argv[i - 1] = argv[i]; + --*argc; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optExecute + * + * FUNCTION Perform the action of an option. + * + * INPUT opt array of possible options. + * arg argument to option, if it applies. + * lng was the option given as a long option? + * + * RETURNS Nothing. Aborts in case of error. + * + */ +void optExecute(const optStruct *opt, char *arg, int lng) +{ + switch (opt->type) { + case OPT_FLAG: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(void)) opt->arg)(); + else + *((int *) opt->arg) = 1; + break; + + case OPT_STRING: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(char *)) opt->arg)(arg); + else + *((char **) opt->arg) = arg; + break; + + case OPT_INT: + case OPT_LONG: { + long tmp; + char *e; + + tmp = strtol(arg, &e, 10); + if (*e) + optFatal(_("invalid number `%s'\n"), arg); + if (errno == ERANGE + || (opt->type == OPT_INT && (tmp > INT_MAX || tmp < INT_MIN))) + optFatal(_("number `%s' to `%s' out of range\n"), + arg, optString(opt, lng)); + if (opt->type == OPT_INT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(int)) opt->arg)((int) tmp); + else + *((int *) opt->arg) = (int) tmp; + } else /* OPT_LONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(long)) opt->arg)(tmp); + else + *((long *) opt->arg) = tmp; + } + break; + } + + case OPT_UINT: + case OPT_ULONG: { + unsigned long tmp; + char *e; + + tmp = strtoul(arg, &e, 10); + if (*e) + optFatal(_("invalid number `%s'\n"), arg); + if (errno == ERANGE + || (opt->type == OPT_UINT && tmp > UINT_MAX)) + optFatal(_("number `%s' to `%s' out of range\n"), + arg, optString(opt, lng)); + if (opt->type == OPT_UINT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned)) opt->arg)((unsigned) tmp); + else + *((unsigned *) opt->arg) = (unsigned) tmp; + } else /* OPT_ULONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned long)) opt->arg)(tmp); + else + *((unsigned long *) opt->arg) = tmp; + } + break; + } + + default: + break; + } +} + + + +/************************************************************************** + * * + * P U B L I C F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optSetFatalFunc + * + * FUNCTION Set function used to display error message and exit. + * + * SYNOPSIS #include "shhmsg.h" + * void optSetFatalFunc(void (*f)(const char *, ...)); + * + * INPUT f function accepting printf()'like parameters, + * that _must_ abort the program. + * + */ +void optSetFatalFunc(void (*f)(const char *, ...)) +{ + optFatal = f; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optParseOptions + * + * FUNCTION Parse commandline options. + * + * SYNOPSIS #include "shhopt.h" + * void optParseOptions(int *argc, char *argv[], + * const optStruct opt[], int allowNegNum); + * + * INPUT argc Pointer to number of options. + * argv Array of option-/argument-strings. + * opt Array of possible options. + * allowNegNum + * a negative number is not to be taken as + * an option. + * + * OUTPUT argc new argument count. + * argv array with arguments removed. + * + * RETURNS Nothing. Aborts in case of error. + * + * DESCRIPTION This function checks each option in the argv-array + * against strings in the opt-array, and `executes' any + * matching action. Any arguments to the options are + * extracted and stored in the variables or passed to + * functions pointed to by entries in opt. + * + * Options and arguments used are removed from the argv- + * array, and argc is decreased accordingly. + * + * Any error leads to program abortion. + * + */ +void optParseOptions(int *argc, char *argv[], + const optStruct opt[], int allowNegNum) +{ + int ai, /* argv index. */ + optarg, /* argv index of option argument, or -1 if none. */ + mi, /* Match index in opt. */ + done; + char *arg, /* Pointer to argument to an option. */ + *o, /* pointer to an option character */ + *p; + + /* + * Loop through all arguments. + */ + for (ai = 0; ai < *argc; ) { + /* + * "--" indicates that the rest of the argv-array does not + * contain options. + */ + if (strcmp(argv[ai], "--") == 0) { + argvRemove(argc, argv, ai); + break; + } + + if (allowNegNum && argv[ai][0] == '-' && isdigit(argv[ai][1])) { + ++ai; + continue; + } else if (strncmp(argv[ai], "--", 2) == 0) { + /* long option */ + /* find matching option */ + if ((mi = optMatch(opt, argv[ai] + 2, 1)) < 0) + optFatal(_("unrecognized option `%s'\n"), argv[ai]); + + /* possibly locate the argument to this option. */ + arg = NULL; + if ((p = strchr(argv[ai], '=')) != NULL) + arg = p + 1; + + /* does this option take an argument? */ + optarg = -1; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + if (!arg) { + if ((optarg = ai + 1) == *argc) + optFatal(_("option `%s' requires an argument\n"), + optString(&opt[mi], 1)); + arg = argv[optarg]; + } + } else { + if (arg) + optFatal(_("option `%s' doesn't allow an argument\n"), + optString(&opt[mi], 1)); + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 1); + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else if (*argv[ai] == '-') { + /* A dash by itself is not considered an option. */ + if (argv[ai][1] == '\0') { + ++ai; + continue; + } + /* Short option(s) following */ + o = argv[ai] + 1; + done = 0; + optarg = -1; + while (*o && !done) { + /* find matching option */ + if ((mi = optMatch(opt, o, 0)) < 0) + optFatal(_("unrecognized option `-%c'\n"), *o); + + /* does this option take an argument? */ + optarg = -1; + arg = NULL; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + arg = o + 1; + if (!*arg) { + if ((optarg = ai + 1) == *argc) + optFatal(_("option `%s' requires an argument\n"), + optString(&opt[mi], 0)); + arg = argv[optarg]; + } + done = 1; + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 0); + ++o; + } + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else { + /* a non-option argument */ + ++ai; + } + } +} diff --git a/sys-utils/shhopt.h b/clock/shhopt.h similarity index 100% rename from sys-utils/shhopt.h rename to clock/shhopt.h diff --git a/clockB/Makefile b/clockB/Makefile new file mode 100644 index 00000000..1a2f4ecd --- /dev/null +++ b/clockB/Makefile @@ -0,0 +1,31 @@ +# Makefile -- Makefile for util-linux Linux utilities +# +include ../make_include +include ../MCONFIG + +# Where to put man pages? + +MAN8= hwclock.8 + +# Where to put binaries? +# See the "install" rule for the links. . . + +SBIN= hwclock + + +all: $(SBIN) + + +CFLAGS = -s -Wall -Wwrite-strings -Wstrict-prototypes -Winline $(CDEBUG) + +hwclock: hwclock.o rtc.o directio.o kd.o util.o shhopt.o +hwclock.o: shhopt.h +hwclock.o rtc.o directio.o kd.o util.o: hwclock.h + +install: all + $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR) + $(INSTALLBIN) $(SBIN) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +clean: + -rm -f *.o *~ core $(SBIN) diff --git a/clockB/directio.c b/clockB/directio.c new file mode 100644 index 00000000..d3a77eb1 --- /dev/null +++ b/clockB/directio.c @@ -0,0 +1,727 @@ +/************************************************************************** + + This is a component of the hwclock program. + + This file contains the code for accessing the hardware clock via + direct I/O (kernel-style input and output operations) as opposed + to via a device driver. + + + MAINTENANCE NOTES + + Here is some information on how the Hardware Clock works, from + unknown source and authority. In theory, the specification for this + stuff is the specification of Motorola's MC146818A clock chip, used + in the early ISA machines. Subsequent machines should have copied + its function exactly. In reality, though, the copies are inexact + and the MC146818A itself may fail to implement its specifications, + and we have just have to work with whatever is there (actually, + anything that Windows works with, because that's what determines + whether broken hardware has to be fixed!). + + i386 CMOS starts out with 14 bytes clock data + alpha has something similar, but with details + depending on the machine type. + + byte 0: seconds (0-59) + byte 2: minutes (0-59) + byte 4: hours (0-23 in 24hr mode, + 1-12 in 12hr mode, with high bit unset/set if am/pm) + byte 6: weekday (1-7, Sunday=1) + byte 7: day of the month (1-31) + byte 8: month (1-12) + byte 9: year (0-99) + + + Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set + The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set + The clock is undefined (being updated) if bit 7 of byte 10 is set. + The clock is frozen (to be updated) by setting bit 7 of byte 11 + Bit 7 of byte 14 indicates whether the CMOS clock is reliable: + it is 1 if RTC power has been good since this bit was last read; + it is 0 when the battery is dead and system power has been off. + + The century situation is messy: + + Usually byte 50 (0x32) gives the century (in BCD, so 0x19 or 0x20 in + pure binary), but IBM PS/2 has (part of) a checksum there and uses + byte 55 (0x37). Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 + gives the century. The original RTC will not access any century + byte; some modern versions will. If a modern RTC or BIOS increments + the century byte it may go from 0x19 to 0x20, but in some buggy + cases 0x1a is produced. + + CMOS byte 10 (clock status register A) has 3 bitfields: + bit 7: 1 if data invalid, update in progress (read-only bit) + (this is raised 224 us before the actual update starts) + 6-4 select base frequency + 010: 32768 Hz time base (default) + 111: reset + all other combinations are manufacturer-dependent + (e.g.: DS1287: 010 = start oscillator, anything else = stop) + 3-0 rate selection bits for interrupt + 0000 none + 0001, 0010 give same frequency as 1000, 1001 + 0011 122 microseconds (minimum, 8192 Hz) + .... each increase by 1 halves the frequency, doubles the period + 1111 500 milliseconds (maximum, 2 Hz) + 0110 976.562 microseconds (default 1024 Hz) + + Avoid setting the RTC clock within 2 seconds of the day rollover + that starts a new month or enters daylight saving time. + +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#if defined(__i386__) || defined(__alpha__) +#include /* for inb, outb */ +#else +void outb(int a, int b){} +int inb(int c){ return 0; } +#endif + +#include "hwclock.h" + +#define BCD_TO_BIN(val) (((val)&0x0f) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) + + +/*---------------------------------------------------------------------------- + ATOMIC_TOP and ATOMIC_BOTTOM are wierd macros that help us to do + atomic operations when we do ugly low level I/O. + + You put ATOMIC_TOP above some code and ATOMIC_BOTTOM below it and + it makes sure all the enclosed code executes without interruption + by some other process (and, in some cases, even the kernel). + + These work fundamentally differently depending on the machine + architecture. In the case of a x86, it simply turns interrupts off + at the top and turns them back on at the bottom. + + For Alpha, we can't mess with interrupts (we shouldn't for x86 + either, but at least it tends to work!), so instead we start a loop + at the top and close it at the bottom. This loop repeats the + enclosed code until the upper 32 bits of the cycle counter are the + same before and after. That means there was no context change + while the enclosed code was executing. + + For other architectures, we do nothing, and the atomicity is only + feigned. + +-----------------------------------------------------------------------------*/ + +#if defined(__i386__) +#define ATOMIC_TOP \ + { \ + const bool interrupts_were_enabled = interrupts_enabled; \ + __asm__ volatile ("cli"); \ + interrupts_enabled = FALSE; + +#define ATOMIC_BOTTOM \ + if (interrupts_were_enabled) { \ + __asm__ volatile ("sti"); \ + interrupts_enabled = TRUE; \ + } \ + } +#elif defined(__alpha__) +#define ATOMIC_TOP \ + { \ + unsigned long ts1, ts2, n; \ + n = 0; \ + do { \ + asm volatile ("rpcc %0" : "r="(ts1)); + +#define ATOMIC_BOTTOM \ + asm volatile ("rpcc %0" : "r="(ts2)); \ + n++; \ + } while ((ts1 ^ ts2) >> 32 != 0); \ + } +#else +#define ATOMIC_BOTTOM +#define ATOMIC_TOP +#endif + + +#if defined(__i386__) || defined(__alpha__) +/* The following are just constants. Oddly, this program will not + compile if the inb() and outb() functions use something even + slightly different from these variables. This is probably at least + partially related to the fact that __builtin_constant_p() doesn't + work (is never true) in an inline function. See comment to this + effect in asm/io.h. +*/ +static unsigned short clock_ctl_addr = 0x70; +static unsigned short clock_data_addr = 0x71; +#endif + + +static bool interrupts_enabled; + /* Interrupts are enabled as normal. We, unfortunately, turn interrupts + on the machine off in some places where we do the direct ISA accesses + to the Hardware Clock. It is in extremely poor form for a user space + program to do this, but that's the price we have to pay to run on an + ISA machine without the rtc driver in the kernel. + + Code which turns interrupts off uses this value to determine if they + need to be turned back on. + */ + + +void +assume_interrupts_enabled(void) { + interrupts_enabled = TRUE; +} + + + +static int +i386_iopl(const int level) { +/*---------------------------------------------------------------------------- + When compiled for an Intel target, this is just the iopl() kernel call. + When compiled for any other target, this is a dummy function. + + We do it this way in order to keep the conditional compilation stuff + out of the way so it doesn't mess up readability of the code. +-----------------------------------------------------------------------------*/ +#ifdef __i386__ + extern int iopl(int level); + return iopl(level); +#else + return -1; +#endif +} + + + +bool +uf_bit_needed(const bool user_wants_uf) { +/*---------------------------------------------------------------------------- + Return true iff the UIP bit doesn't work on this hardware clock, so + we will need to use the UF bit to synchronize with the clock (if in + fact we synchronize using direct I/O to the clock). + + To wit, we need to use the UF bit on a DEC Alpha PC164/LX164/SX164. + Or, of course, if the user told us to. +-----------------------------------------------------------------------------*/ + bool retval; + + if (user_wants_uf) retval = TRUE; + else { + if (alpha_machine && ( + is_in_cpuinfo("system variation", "PC164") || + is_in_cpuinfo("system variation", "LX164") || + is_in_cpuinfo("system variation", "SX164"))) + retval = TRUE; + else retval = FALSE; + } + if (debug && retval) + printf("We will be using the UF bit instead of the usual " + "UIP bit to synchronize with the clock, as required on " + "certain models of DEC Alpha.\n"); + + return retval; +} + + + +int +zero_year(const bool arc_opt, const bool srm_opt) { +/*---------------------------------------------------------------------------- + Return the year of the century (e.g. 0) to which a zero value in + the year register of the hardware clock applies (or at least what + we are to assume -- nobody can say for sure!) + + 'arc_opt' and 'srm_opt' are the true iff the user specified the + corresponding invocation option to instruct us that the machine is an + Alpha with ARC or SRM console time. + + A note about hardware clocks: + + ISA machines are simple: the year register is a year-of-century + register, so the zero year is zero. On Alphas, we may see 1980 or + 1952 (Digital Unix?) or 1958 (ALPHA_PRE_V1_2_SRM_CONSOLE) +-----------------------------------------------------------------------------*/ + int retval; /* our return value */ + + if (arc_opt || srm_opt) { + /* User is telling us what epoch his machine uses. Believe it. */ + if (arc_opt) retval = 0; + else retval = 0; + } else { + unsigned long kernel_epoch; + char *reason; /* malloc'ed */ + + get_epoch(&kernel_epoch, &reason); + if (reason == NULL) retval = kernel_epoch; + else { + /* OK, the user doesn't know and the kernel doesn't know; + figure it out from the machine model + */ + free(reason); /* Don't care about kernel's excuses */ + /* See whether we are dealing with SRM or MILO, as they have + different "epoch" ideas. */ + if (is_in_cpuinfo("system serial number", "MILO")) { + if (debug) printf("booted from MILO\n"); + /* See whether we are dealing with a RUFFIAN aka UX, as they + have REALLY different TOY (TimeOfYear) format: BCD, and not + an ARC-style epoch. BCD is detected dynamically, but we + must NOT adjust like ARC. + */ + if (is_in_cpuinfo("system type", "Ruffian")) { + if (debug) printf("Ruffian BCD clock\n"); + retval = 0; + } else { + if (debug) printf("Not Ruffian BCD clock\n"); + retval = 80; + } + } else { + if (debug) printf("Not booted from MILO\n"); + retval = 0; + } + } + } + return retval; +} + + + +static inline unsigned char +hclock_read(const unsigned char reg, const int dev_port) { +/*--------------------------------------------------------------------------- + Relative byte 'reg' of the Hardware Clock value. + + Get this with direct CPU I/O instructions. If 'dev_port' is not -1, + use the /dev/port device driver (via the 'dev_port' file descriptor) + to do this I/O. Otherwise, use the kernel's inb()/outb() facility. + + On a system without the inb()/outb() facility, if 'dev_port' is -1, + just return 0. + + Results undefined if 'reg' is out of range. +---------------------------------------------------------------------------*/ + unsigned char ret; + + ATOMIC_TOP + if (dev_port >= 0) { + const unsigned char v = reg | 0x80; + lseek(dev_port, 0x170, 0); + write(dev_port, &v, 1); + lseek(dev_port, 0x171, 0); + read(dev_port, &ret, 1); + } else { +#if defined(__i386__) || defined(__alpha__) + /* & 0x7f ensures that we are not disabling NMI while we read. + Setting on Bit 7 here would disable NMI + + Various docs suggest that one should disable NMI while + reading/writing CMOS data, and enable it again afterwards. + This would yield the sequence + outb (reg | 0x80, 0x70); + val = inb(0x71); + outb (0x0d, 0x70); // 0x0d: random read-only location + Other docs state that "any write to 0x70 should be followed + by an action to 0x71 or the RTC wil be left in an unknown state". + Most docs say that it doesn't matter at all what one does. + */ + outb(reg & 0x7f, clock_ctl_addr); + ret = inb(clock_data_addr); +#else + ret = 0; +#endif + } + ATOMIC_BOTTOM + return ret; +} + + + +static inline void +hclock_write(unsigned char reg, unsigned char val, const int dev_port) { +/*---------------------------------------------------------------------------- + Set relative byte 'reg' of the Hardware Clock value to 'val'. + Do this with the kernel's outb() function if 'dev_port' is -1, but + if not, use the /dev/port device (via the 'dev_port' file descriptor), + which is almost the same thing. + + On a non-ISA, non-Alpha machine, if 'dev_port' is -1, do nothing. +----------------------------------------------------------------------------*/ + if (dev_port >= 0) { + unsigned char v; + v = reg | 0x80; + lseek(dev_port, 0x170, 0); + write(dev_port, &v, 1); + v = (val & 0xff); + lseek(dev_port, 0x171, 0); + write(dev_port, &v, 1); + } else { +#if defined(__i386__) || defined(__alpha__) + /* & 0x7f ensures that we are not disabling NMI while we read. + Setting on Bit 7 here would disable NMI + */ + outb(reg & 0x7f, clock_ctl_addr); + outb(val, clock_data_addr); +#endif + } +} + + + +static inline int +hardware_clock_busy(const int dev_port, const bool use_uf_bit) { +/*---------------------------------------------------------------------------- + Return whether the hardware clock is in the middle of an update + (which happens once each second). + + Use the clock's UIP bit (bit 7 of Control Register A) to tell + unless 'use_uf_bit' is true, in which case use the UF bit (bit 4 of + Control Register C). +-----------------------------------------------------------------------------*/ + return + use_uf_bit ? (hclock_read(12, dev_port) & 0x10) : + (hclock_read(10, dev_port) & 0x80); +} + + + +void +synchronize_to_clock_tick_ISA(int *retcode_p, const int dev_port, + const bool use_uf_bit) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for ISA. +-----------------------------------------------------------------------------*/ + int i; /* local loop index */ + + /* Wait for rise. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + for (i = 0; + !hardware_clock_busy(dev_port, use_uf_bit) && (i < 10000000); + i++); + if (i >= 10000000) *retcode_p = 1; + else { + /* Wait for fall. Should be within 2.228 ms. */ + for (i = 0; + hardware_clock_busy(dev_port, use_uf_bit) && (i < 1000000); + i++); + if (i >= 10000000) *retcode_p = 1; + else *retcode_p = 0; + } +} + + + +void +read_hardware_clock_isa(struct tm *tm, const int dev_port, + int hc_zero_year) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via argument. + Assume we have an ISA machine and read the clock directly with CPU I/O + instructions. If 'dev_port' isn't -1, use the /dev/port facility to + do this I/O. Otherwise, use the kernel's inb()/outb() service. + + This function is not totally reliable. It takes a finite and + unpredictable amount of time to execute the code below. During that + time, the clock may change and we may even read an invalid value in + the middle of an update. We do a few checks to minimize this + possibility, but only the kernel can actually read the clock + properly, since it can execute code in a short and predictable + amount of time (by turning off interrupts). + + In practice, the chance of this function returning the wrong time is + extremely remote. + +-----------------------------------------------------------------------------*/ + bool got_time; + /* We've successfully read a time from the Hardware Clock */ + int attempts; + /* Number of times we've tried to read the clock. This only + matters because we will give up (and proceed with garbage in + variables) rather than hang if something is broken and we are + never able to read the clock + */ + int hclock_sec = 0, hclock_min = 0, hclock_hour = 0, hclock_wday = 0, + hclock_mon = 0, hclock_mday = 0, hclock_year = 0; + /* The values we got from the Hardware Clock's registers, assuming + they are in pure binary. + */ + + int status = 0; /* Hardware Clock status register, as if pure binary */ + int adjusted_year; + int ampmhour; + int pmbit; + + got_time = FALSE; + attempts = 0; /* initial value */ + while (!got_time && attempts++ < 1000000) { + /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress + (UIP) bit, which is on while and 244 uS before the Hardware Clock + updates itself. It updates the counters individually, so reading + them during an update would produce garbage. The update takes 2mS, + so we could be spinning here that long waiting for this bit to turn + off. + + Furthermore, it is pathologically possible for us to be in this + code so long that even if the UIP bit is not on at first, the + clock has changed while we were running. We check for that too, + and if it happens, we start over. + */ + + if ((hclock_read(10, dev_port) & 0x80) == 0) { + /* No clock update in progress, go ahead and read */ + + status = hclock_read(11, dev_port); + + hclock_sec = hclock_read(0, dev_port); + hclock_min = hclock_read(2, dev_port); + hclock_hour = hclock_read(4, dev_port); + hclock_wday = hclock_read(6, dev_port); + hclock_mday = hclock_read(7, dev_port); + hclock_mon = hclock_read(8, dev_port); + hclock_year = hclock_read(9, dev_port); + /* Unless the clock changed while we were reading, consider this + a good clock read . + */ + if (hclock_sec == hclock_read(0, dev_port)) got_time = TRUE; + /* Yes, in theory we could have been running for 60 seconds and + the above test wouldn't work! + */ + } + } + + if (!(status & 0x04)) { + /* The hardware clock is in BCD mode. This is normal. */ + tm->tm_sec = BCD_TO_BIN(hclock_sec); + tm->tm_min = BCD_TO_BIN(hclock_min); + ampmhour = BCD_TO_BIN(hclock_hour & 0x7f); + pmbit = hclock_hour & 0x80; + tm->tm_wday = BCD_TO_BIN(hclock_wday) - 1; /* Used to be 3. Why?? */ + tm->tm_mday = BCD_TO_BIN(hclock_mday); + tm->tm_mon = BCD_TO_BIN(hclock_mon) - 1; + adjusted_year = BCD_TO_BIN(hclock_year); + } else { + /* The hardware clock registers are in pure binary format. */ + tm->tm_sec = hclock_sec; + tm->tm_min = hclock_min; + ampmhour = hclock_hour & 0x7f; + pmbit = hclock_hour & 0x80; + tm->tm_wday = hclock_wday - 1; /* Used to be 3. Why?? */ + tm->tm_mday = hclock_mday; + tm->tm_mon = hclock_mon - 1; + adjusted_year = hclock_year; + } + + if (!(status & 0x02)) { + /* Clock is in 12 hour (am/pm) mode. This is unusual. */ + if (pmbit == 0x80) { + if (ampmhour == 12) tm->tm_hour = 12; + else tm->tm_hour = 12 + ampmhour; + } else { + if (ampmhour ==12) tm->tm_hour = 0; + else tm->tm_hour = ampmhour; + } + } else { + /* Clock is in 24 hour mode. This is normal. */ + tm->tm_hour = ampmhour; + } + /* We don't use the century byte (Byte 50) of the Hardware Clock. + Here's why: It didn't exist in the original ISA specification, + so old machines don't have it, and even some new ones don't. + Some machines, including the IBM Valuepoint 6387-X93, use that + byte for something else. Some machines have the century in + Byte 55. + + 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 + 2000's, otherwise it's the 1900's. + + Alpha machines (some, anyway) don't have this ambiguity + because they do not have a year-of-century register. We + pretend they do anyway, for simplicity and to avoid + recognizing times that can't be represented in Linux standard + time. So even though we already have enough information to + know that the clock says 2050, we will render it as 1950. + */ + { + const int year_of_century = (adjusted_year + hc_zero_year) % 100; + if (year_of_century >= 37) tm->tm_year = year_of_century; + else tm->tm_year = year_of_century + 100; + } + tm->tm_isdst = -1; /* don't know whether it's daylight */ +} + + + +void +set_hardware_clock_isa(const struct tm new_tm, + const int hc_zero_year, + const int dev_port, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time (in broken down format) + new_tm. Use direct I/O instructions to what we assume is + an ISA Hardware Clock. + + Iff 'dev_port' is -1, use the kernel inb()/outb() service, otherwise + use the /dev/port device (via file descriptor 'dev_port') + to do those I/O instructions. +----------------------------------------------------------------------------*/ + unsigned char save_control, save_freq_select; + + if (testing) + printf("Not setting Hardware Clock because running in test mode.\n"); + else { + int ampmhour; + /* The hour number that goes into the hardware clock, taking into + consideration whether the clock is in 12 or 24 hour mode + */ + int pmbit; + /* Value to OR into the hour register as the am/pm bit */ + const int adjusted_year = + (new_tm.tm_year - hc_zero_year)%100; + /* The number that goes in the hardware clock's year register */ + + int hclock_sec, hclock_min, hclock_hour, hclock_wday, hclock_mon, + hclock_mday, hclock_year; + /* The values we will put, in pure binary, in the Hardware Clock's + registers. + */ + + ATOMIC_TOP + + save_control = hclock_read(11, dev_port); + /* tell the clock it's being set */ + hclock_write(11, (save_control | 0x80), dev_port); + save_freq_select = hclock_read(10, dev_port); + /* stop and reset prescaler */ + hclock_write (10, (save_freq_select | 0x70), dev_port); + + + if (!(save_control & 0x02)) { + /* Clock is in 12 hour (am/pm) mode. This is unusual. */ + if (new_tm.tm_hour == 0) { + ampmhour = 12; + pmbit = 0x00; + } else if (new_tm.tm_hour < 12) { + ampmhour = new_tm.tm_hour; + pmbit = 0x00; + } else if (new_tm.tm_hour == 12) { + ampmhour = 12; + pmbit = 0x80; + } else { + ampmhour = new_tm.tm_hour - 12; + pmbit = 0x80; + } + } else { + /* Clock is in 24 hour mode. This is normal. */ + ampmhour = new_tm.tm_hour; + pmbit = 0x00; + } + + + if (!(save_control & 0x04)) { + /* Clock's registers are in BCD. This is normal. */ + hclock_sec = BIN_TO_BCD(new_tm.tm_sec); + hclock_min = BIN_TO_BCD(new_tm.tm_min); + hclock_hour = pmbit | BIN_TO_BCD(ampmhour); + hclock_wday = BIN_TO_BCD(new_tm.tm_wday + 1); /* Used to be 3. Why??*/ + hclock_mday = BIN_TO_BCD(new_tm.tm_mday); + hclock_mon = BIN_TO_BCD(new_tm.tm_mon + 1); + hclock_year = BIN_TO_BCD(adjusted_year); + } else { + /* Clock's registers are in pure binary. This is unusual. */ + hclock_sec = new_tm.tm_sec; + hclock_min = new_tm.tm_min; + hclock_hour = pmbit | ampmhour; + hclock_wday = new_tm.tm_wday + 1; /* Used to be 3. Why?? */ + hclock_mday = new_tm.tm_mday; + hclock_mon = new_tm.tm_mon + 1; + hclock_year = adjusted_year; + } + + hclock_write(0, hclock_sec, dev_port); + hclock_write(2, hclock_min, dev_port); + hclock_write(4, hclock_hour, dev_port); + hclock_write(6, hclock_wday, dev_port); + hclock_write(7, hclock_mday, dev_port); + hclock_write(8, hclock_mon, dev_port); + hclock_write(9, hclock_year, dev_port); + + /* We don't set the century byte (usually Byte 50) because it isn't + always there. (see further comments in read_hardware_clock_isa). + In previous releases, we did. + */ + + /* The kernel sources, linux/arch/i386/kernel/time.c, have the + following comment: + + The following flags have to be released exactly in this order, + otherwise the DS12887 (popular MC146818A clone with integrated + battery and quartz) will not reset the oscillator and will not + update precisely 500 ms later. You won't find this mentioned + in the Dallas Semiconductor data sheets, but who believes data + sheets anyway ... -- Markus Kuhn + + Hence, they will also be done in this order here. + faith@cs.unc.edu, Thu Nov 9 08:26:37 1995 + */ + + hclock_write (11, save_control, dev_port); + hclock_write (10, save_freq_select, dev_port); + + ATOMIC_BOTTOM + } +} + + + +void +get_inb_outb_privilege(const enum clock_access_method clock_access, + bool * const no_auth_p) { + + if (clock_access == ISA) { + const int rc = i386_iopl(3); + if (rc != 0) { + fprintf(stderr, MYNAME " is unable to get I/O port access. " + "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); + *no_auth_p = TRUE; + } else *no_auth_p = FALSE; + } else *no_auth_p = FALSE; +} + + + +void +get_dev_port_access(const enum clock_access_method clock_access, + int * dev_port_p) { + + if (clock_access == DEV_PORT) { + /* Get the /dev/port file open */ + *dev_port_p = open("/dev/port", O_RDWR); + if (*dev_port_p < 0) { + fprintf(stderr, MYNAME "is unable to open the /dev/port file. " + "I.e. open() of the file failed with errno = %s (%d).\n" + "Run with the --debug option and check documentation " + "to find out why we are trying " + "to use /dev/port instead of some other means to access " + "the Hardware Clock.", + strerror(errno), errno); + } + } else *dev_port_p = 0; +} + + + diff --git a/clockB/hwclock.8 b/clockB/hwclock.8 new file mode 100644 index 00000000..0a216840 --- /dev/null +++ b/clockB/hwclock.8 @@ -0,0 +1,599 @@ +.TH CLOCK 8 "02 March 1998" +.SH NAME +clock \- query and set the hardware clock (RTC) +.SH SYNOPSIS +.B "hwclock --show" +.br +.B "hwclock --set --date=newdate" +.br +.B "hwclock --systohc" +.br +.B "hwclock --hctosys" +.br +.B "hwclock --getepoch" +.br +.B "hwclock --setepoch --epoch=year" +.br +.B "hwclock --adjust" +.br +.B "hwclock --version" +.PP +other options: +.PP +.B "--utc --localtime --directisa --test --debug" +.PP +and arcane options for DEC Alpha: +.PP +.B "--arc --jensen --srm --funky-toy" +.PP +Minimum unique abbreviations of all options are acceptable. +.PP +Also, equivalent options -r, -w, -s, -a, -v, -u, -D, -A, -J, -S, and -F +are accepted for compatibility with the program "clock". + +.SH DESCRIPTION +.I hwclock +is a tool for accessing the Hardware Clock. You can display the +current time, set the Hardware Clock to a specified time, set the +Hardware Clock to the System Time, and set the System Time from the +Hardware Clock. +.PP +You can also run +.I hwclock +periodically to insert or remove time from the Hardware Clock to +compensate for systematic drift (where the clock consistently gains or +loses time at a certain rate if left to run). + +.SH OPTIONS +You need exactly one of the following options to tell +.I hwclock +what function to perform: +.PP +.TP +.B \-\-show +Read the Hardware Clock and print the time on Standard Output. +The time is always in local time, even if you keep your Hardware Clock +in Coordinated Universal Time. See the +.B \-\-utc +option. + +.TP +.B \-\-set +Set the Hardware Clock to the time given by the +.B \-\-date +option. +.TP +.B \-\-hctosys +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 +.IR /usr/lib/zoneinfo , +as +.BR 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. +.TP +.B \-\-adjust +Add or subtract time from the Hardware Clock to account for systematic +drift since the last time the clock was set or adjusted. See discussion +below. +.TP +.B \-\-getepoch +Print out standard output the kernel's Hardware Clock epoch value. +This is the number of years into AD to which a zero year value in the +Hardware Clock refers. For example, if you are using the convention +that the year counter in your Hardware Clock contains the number of +full years since 1952, then the kernel's Hardware Counter epoch value +must be 1952. + +This epoch value is used whenever hwclock reads or sets the Hardware Clock. +.TP +.B \-\-setepoch +Set the kernel's Hardware Clock epoch value to the value specified by the +.B \-\-epoch +option. See the +.B \-\-getepoch +option for details. +.TP +.B \-\-version +Print the version of +.I hwclock +on Standard Output. +.br +You need the following option if you specify +.B \-\-set +option. Otherwise, it is ignored. +.TP +.B \-\-date=date_string +Specifies the time to which to set the Hardware Clock. The value of this +option is an argument to the +.I date(1) +program. For example, +.sp +.I hwclock --set --date="9/22/96 16:45:05" +.sp +The argument is in local time, even if you keep your Hardware Clock in +Coordinated Universal time. See the +.I \-\-utc +option. + +.TP +.B \-\-epoch=year +Specifies the year which is the beginning of the Hardware Clock's +epoch. I.e. the number of years into AD to which a zero value in the +Hardware Clock's year counter refers. + +For example, +.sp +.I hwclock --setepoch --epoch=1952 + +.PP +The following options apply to most functions. +.TP +.B \-\-utc +.TP +.B \-\-localtime +Indicates that the Hardware Clock is kept in Coordinated Universal +Time or local time, respectively. 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 +.IR hwclock . + +If you specify the wrong one of these options (or specify neither and +take a wrong default), both setting and querying of the Hardware Clock +will be messed up. + +If you specify neither +.B \-\-utc +nor +.B \-\-localtime +, the default is whichever was specified the last time +.I hwclock +was used to set the clock (i.e. hwclock was successfully run with the +.B \-\-set +, +.B \-\-systohc +, +or +.B \-\-adjust +options), as recorded in the adjtime file. If the adjtime file doesn't +exist, the default is local time. + +.TP +.B \-\-directisa +is meaningful only on an ISA machine or an Alpha (which implements enough +of ISA to be, roughly speaking, an ISA machine for +.IR hwclock 's +purposes). For other machines, it has no effect. This option tells +.I hwclock +to use explicit I/O instructions to access the Hardware Clock. +Without this option, +.I hwclock +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. + +The rtc device driver was new in Linux Release 2. +.TP +.B \-\-badyear +Indicates that the Hardware Clock is incapable of storing years outside +the range 1994-1999. There is a problem in some BIOSes (almost all +Award BIOSes made between 4/26/94 and 5/31/95) wherein they are unable +to deal with years after 1999. If one attempts to set the year-of-century +value to something less than 94 (or 95 in some cases), the value that +actually gets set is 94 (or 95). Thus, if you have one of these machines, +.I hwclock +cannot set the year after 1999 and cannot use the value of the clock as +the true time in the normal way. + +To compensate for this (without your getting a BIOS update, which would +definitely be preferable), always use +.B \-\-badyear +if you have one of these machines. When +.I hwclock +knows it's working with a brain-damaged clock, it ignores the year part of +the Hardware Clock value and instead tries to guess the year based on the +last calibrated date in the adjtime file, by assuming that that date is +within the past year. For this to work, you had better do a +.I hwclock \-\-set +or +.I hwclock \-\-systohc +at least once a year! + +Though +.I hwclock +ignores the year value when it reads the Hardware Clock, it sets the +year value when it sets the clock. It sets it to 1995, 1996, 1997, or +1998, whichever one has the same position in the leap year cycle as +the true year. That way, the Hardware Clock inserts leap days where +they belong. Again, if you let the Hardware Clock run for more than a +year without setting it, this scheme could be defeated and you could +end up losing a day. + +.I hwclock +warns you that you probably need +.B \-\-badyear +whenever it finds your Hardware Clock set to 1994 or 1995. + +.TP +.B \-\-srm +.TP +.B \-\-arc +.TP +.B \-\-jensen +.TP +.B \-\-funky\-toy +These options all tell +.I hwclock +what kind of Alpha machine you have. They +are invalid if you don't have an Alpha and shouldn't be necessary if you +do, because +.I hwclock +should be able to determine by itself what it's +running on. These options make it possible for +.I hwclock +to work even when +its environment does not conform to its expectations and thus it cannot +accurately determine what sort of system it is running on. If you think +hwclock is incorrectly determining the system's characteristics, try +running with the +.B \-\-debug +option to see what conclusions the program is +reaching and how. If you find you need one of these options to make +.I hwclock +work, contact the +.I hwclock +maintainer to see if the program can be improved to detect your system +automatically. + +.B \-\-jensen +means you are running on a Jensen model. + +.B \-\-arc +means your machine is running with ARC console time. + +.B \-\-srm +means your machine is running with SRM console time. + +.B \-\-funky\-toy +means that on your machine, one has to use the UF bit instead +of the UIP bit in the Hardware Clock to detect a time transition. "Toy" +in the option name refers to the Time Of Year facility of the machine. + + +.TP +.B \-\-test +Do everything except actually updating the Hardware Clock or anything +else. This is useful, especially in conjunction with +.B \-\-debug, +in learning about +.I hwclock. +.TP +.B \-\-debug +Display a lot of information about what +.I hwclock +is doing internally. Some of its function is complex and this output +can help you understand how the program works. + + +.SH NOTES + + +.SH Clocks in a Linux System +.PP +There are two main clocks in a Linux system: +.PP +.B The Hardware Clock: +This is a clock that runs independently of any control program running +in the CPU and even when the machine is powered off. + +On an ISA system, this clock is specified as part of the ISA standard. +The control program can read or set this clock to a whole second, but +the control program can also detect the edges of the 1 second clock +ticks, so the clock actually has virtually infinite precision. +.PP +This clock is commonly called the hardware clock, the real time clock, +the RTC, the BIOS clock, and the CMOS clock. Hardware Clock, in its +capitalized form, was coined for use by +.I hwclock +because all of the other names are inappropriate to the point of being +misleading. +.PP +.B The System Time: +This is the time kept by a clock inside the Linux kernel and driven by +a timer interrupt. (On an ISA machine, the timer interrupt is part of +the ISA standard). It has meaning only while Linux is running on the +machine. The System Time is the number of seconds since 00:00:00 +January 1, 1970 UTC (or more succinctly, the number of seconds since +1969). The System Time is not an integer, though. It has virtually +infinite precision. +.PP +The System Time is the time that matters. The Hardware Clock's basic +purpose in a Linux system is to keep time when Linux is not running. You +initialize the System Time to the time from the Hardware Clock when Linux +starts up, and then never use the Hardware Clock again. Note that in DOS, +for which ISA was designed, the Hardware Clock is the only real time clock. +.PP +It is important that the System Time not have any discontinuities such as +would happen if you used the +.BR date (1L) +program to set it while the system is running. You can, however, do whatever +you want to the Hardware Clock while the system is running, and the next +time Linux starts up, it will do so with the adjusted time from the Hardware +Clock. You can also use the program +.BR 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 +.I hwclock +Uses many different ways to get and set Hardware Clock values. +The most normal way is to do I/O to the device special file /dev/rtc, +which is presumed to be driven by the rtc device driver. However, +this method is not always available. For one thing, the rtc driver is +a relatively recent addition to Linux. Older systems don't have it. +Also, though there are versions of the rtc driver that work on DEC +Alphas, there appear to be plenty of Alphas on which the rtc driver +does not work (a common symptom is hwclock hanging). +.PP +On older systems, the method of accessing the Hardware Clock depends on +the system hardware. +.PP +On an ISA system, +.I hwclock +can directly access the "CMOS memory" registers that +constitute the clock, by doing I/O to Ports 0x70 and 0x71. It does +this with actual I/O instructions and consequently can only do it if +running with superuser effective userid. (In the case of a Jensen +Alpha, there is no way for +.I hwclock +to execute those I/O instructions, and so it uses instead the +/dev/port device special file, which provides almost as low-level an +interface to the I/O subsystem). + +This is a really poor method of accessing the clock, for all the +reasons that user space programs are generally not supposed to do +direct I/O and disable interrupts. Hwclock provides it because it is +the only method available on ISA and Alpha systems which don't have +working rtc device drivers available. + +.PP +On an m68k system, +.I hwclock +can access the clock via the console driver, via the device special +file /dev/tty1. +.PP +.I hwclock +tries to use /dev/rtc. If it is compiled for a kernel that doesn't have +that function or it is unable to open /dev/rtc, +.I hwclock +will fall back to another method, if available. On an ISA or Alpha +machine, you can force +.I hwclock +to use the direct manipulation of the CMOS registers without even trying +.I /dev/rtc +by specifying the \-\-directisa option. + + +.SH The Adjust Function +.PP +The Hardware Clock is usually not very accurate. However, much of its +inaccuracy is completely predictable - it gains or loses the same amount +of time every day. This is called systematic drift. +.IR hwclock 's +"adjust" function lets you make systematic corrections to correct the +systematic drift. +.PP +It works like this: +.I hwclock +keeps a file, +.I /etc/adjtime, +that keeps some historical information. This is called the adjtime file. +.PP +Suppose you start with no adjtime file. You issue a +.I hwclock \-\-set +command to set the Hardware Clock to the true current time. +.I Hwclock +creates the adjtime file and records in it the current time as the +last time the clock was calibrated. +5 days +later, the clock has gained 10 seconds, so you issue another +.I hwclock \-\-set +command to set it back 10 seconds. +.I Hwclock +updates the adjtime file to show the current time as the last time the +clock was calibrated, and records 2 seconds per day as the systematic +drift rate. 24 hours go by, and then you issue a +.I hwclock \-\-adjust +command. +.I Hwclock +consults the adjtime file and sees that the clock gains 2 seconds per +day when left alone and that it has been left alone for exactly one +day. So it subtracts 2 seconds from the Hardware Clock. It then +records the current time as the last time the clock was adjusted. +Another 24 hours goes by and you issue another +.I hwclock \-\-adjust. +.I Hwclock +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 (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 +adjustment, what drift rate was assumed in any intervening +adjustments, and the amount by which the clock is presently off. +.PP +A small amount of error creeps in any time +.I hwclock +sets the clock, so it refrains from making an adjustment that would be +less than 1 second. Later on, when you request an adjustment again, +the accumulated drift will be more than a second and +.I hwclock +will do the adjustment then. +.PP +It is good to do a +.I hwclock \-\-adjust +just before the +.I hwclock \-\-hctosys +at system startup time, and maybe periodically while the system is +running via cron. +.PP +The adjtime file, while named for its historical purpose of controlling +adjustments only, actually contains other information for use by hwclock +in remembering information from one invocation to the next. +.PP +The format of the adjtime file is, in ASCII: +.PP +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 +.IR clock ) +as a decimal integer. +.PP +Line 2: 1 number: Resulting number of seconds since 1969 UTC of most +recent calibration. Zero if there has been no calibration yet or it +is known that any previous calibration is moot (for example, because +the Hardware Clock has been found, since that calibration, not to +contain a valid time). This is a decimal integer. +.PP +Line 3: "UTC" or "LOCAL". Tells whether the Hardware Clock is set to +Coordinated Universal Time or local time. You can always override this +value with options on the +.I hwclock +command line. +.PP +You can use an adjtime file that was previously used with the +.I clock +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 +.IR "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 +.IR "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 ISA Hardware Clock Century value + +There is some sort of standard that defines CMOS memory Byte 50 on an ISA +machine as an indicator of what century it is. +.I hwclock +does not use or set that byte because there are some machines that +don't define the byte that way, and it really isn't necessary anyway, +since the year-of-century does a good job of implying which century it +is. + +If you have a bona fide use for a CMOS century byte, contact the +.I hwclock +maintainer; an option may be appropriate. + +Note that this section is only relevant when you are using the "direct +ISA" method of accessing the Hardware Clock. + + + +.SH "ENVIRONMENT VARIABLES" +.I TZ + +.SH FILES +.I /etc/adjtime +.I /usr/lib/zoneinfo/ +.I /dev/rtc +.I /dev/port +.I /dev/tty1 +.I /proc/cpuinfo + +.SH "SEE ALSO" +.BR adjtimex (8), +.BR date (1), +.BR gettimeofday (2), +.BR settimeofday (2), +.BR crontab (1), +.BR tzset (3) + +.SH AUTHORS +Written By Bryan Henderson, September 1996 (bryanh@giraffe-data.com), +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/clockB/hwclock.c b/clockB/hwclock.c new file mode 100644 index 00000000..e7f1c919 --- /dev/null +++ b/clockB/hwclock.c @@ -0,0 +1,1744 @@ +/************************************************************************** + hwclock +*************************************************************************** + + This is a program for reading and setting the Hardware Clock on an ISA + family computer. This is the clock that is also known as the RTC, + real time clock, or, unfortunately, the CMOS clock. + + See man page for details. + + By Bryan Henderson, 96.09.19. bryanh@giraffe-data.com + + Based on work by others; see history at end of source code. + +**************************************************************************/ +/************************************************************************** + Maintenance notes + + To compile this, you must use GNU compiler optimization (-O option) + in order to make the "extern inline" functions from asm/io.h (inb(), + etc.) compile. If you don't optimize, which means the compiler + will generate no inline functions, the references to these functions + in this program will be compiled as external references. Since you + probably won't be linking with any functions by these names, you will + have unresolved external references when you link. + + The program is designed to run setuid superuser, since we need to be + able to do direct I/O. (More to the point: we need permission to + execute the iopl() system call). (However, if you use one of the + methods other than direct ISA I/O to access the clock, no setuid is + required). + + Here's some info on how we must deal with the time that elapses while + this program runs: There are two major delays as we run: + + 1) Waiting up to 1 second for a transition of the Hardware Clock so + we are synchronized to the Hardware Clock. + + 2) Running the "date" program to interpret the value of our --date + option. + + Reading the /etc/adjtime file is the next biggest source of delay and + uncertainty. + + The user wants to know what time it was at the moment he invoked us, + not some arbitrary time later. And in setting the clock, he is + giving us the time at the moment we are invoked, so if we set the + clock some time later, we have to add some time to that. + + So we check the system time as soon as we start up, then run "date" + and do file I/O if necessary, then wait to synchronize with a + Hardware Clock edge, then check the system time again to see how + much time we spent. We immediately read the clock then and (if + appropriate) report that time, and additionally, the delay we measured. + + If we're setting the clock to a time given by the user, we wait some + more so that the total delay is an integral number of seconds, then + set the Hardware Clock to the time the user requested plus that + integral number of seconds. N.B. The Hardware Clock can only be set + in integral seconds. + + If we're setting the clock to the system clock value, we wait for + the system clock to reach the top of a second, and then set the + Hardware Clock to the system clock's value. + + Here's an interesting point about setting the Hardware Clock: On my + machine, when you set it, it sets to that precise time. But one can + imagine another clock whose update oscillator marches on a steady one + second period, so updating the clock between any two oscillator ticks + is the same as updating it right at the earlier tick. To avoid any + complications that might cause, we set the clock as soon as possible + after an oscillator tick. + + + About synchronizing to the Hardware Clock when reading the time: The + precision of the Hardware Clock counters themselves is one second. + You can't read the counters and find out that is 12:01:02.5. But if + you consider the location in time of the counter's ticks as part of + its value, then its precision is as infinite as time is continuous! + What I'm saying is this: To find out the _exact_ time in the + hardware clock, we wait until the next clock tick (the next time the + second counter changes) and measure how long we had to wait. We + then read the value of the clock counters and subtract the wait time + and we know precisely what time it was when we set out to query the + time. + + hwclock uses this method, and considers the Hardware Clock to have + infinite precision. + + Definition of century: In this program, a century is a 100 year + period in which all the years' numbers in the Gregorian calendar + differ only in their last two decimal digits. E.g. 1900-1999 is + a century. The 20th Century (1901-2000), however, is not. + + + About the unusual situation of the Jensen variety of Alpha: + + Martin Ostermann writes: + + The problem with the Jensen is twofold: First, it has the clock at a + different address. Secondly, it has a distinction beween "local" and + normal bus addresses. The local ones pertain to the hardware integrated + into the chipset, like serial/parallel ports and of course, the RTC. + Those need to be addressed differently. This is handled fine in the kernel, + and it's not a problem, since this usually gets totally optimized by the + compile. But the i/o routines of (g)libc lack this support so far. + The result of this is, that the old clock program worked only on the + Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb + functions. + + + + Enhancements needed: + + - When waiting for whole second boundary in set_hardware_clock_exact, + fail if we miss the goal by more than .1 second, as could happen if + we get pre-empted (by the kernel dispatcher). + +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shhopt.h" +#include "../version.h" /* Defines UTIL_LINUX, among other things */ +#include "hwclock.h" + +#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); + +/* Here the information for time adjustments is kept. */ +#define ADJPATH "/etc/adjtime" + +/* Note that we must define the boolean type as int because we use the + shhopt option processing library which, unfortunately, returns flag + options as integers. It is customary to define bool as char, but + then we would have to do a lot of conversion in order to interface + with shhopt. +*/ + +/* The following are times, in unix standard format (seconds since 1969) */ +#define START_OF_1994 757411200 +#define END_OF_1995 820396800 + +struct adjtime { + /* This is information we keep in the adjtime file that tells us how + to do drift corrections, among other things. Elements are all + straight from the adjtime file, so see documentation of that file + for details. Exception is , which is an indication that + what's in this structure is not what's in the disk file (because + it has been updated since read from the disk file). + */ + + bool dirty; + float drift_factor; + time_t last_adj_time; + float not_adjusted; + time_t last_calib_time; + /* The most recent time that we set the clock from an external + authority (as opposed to just doing a drift adjustment) + */ + enum a_local_utc {LOCAL, UTC} local_utc; + /* To which time zone, local or UTC, we most recently set the + hardware clock. + */ +}; + + + + + +bool debug; + /* We are running in debug mode, wherein we put a lot of information about + what we're doing to standard output. Because of the pervasive and yet + background nature of this value, this is a global variable. */ + + + +/* We're going to assume that if the CPU is in the Intel x86 family, + this is an ISA family machine. For all practical purposes, this is + the case at the time of this writing, especially after we assume a + Linux kernel is running on it. + */ +const bool isa_machine = +#ifdef __i386__ +TRUE +#else +FALSE; +#endif +; + +const bool alpha_machine = +#ifdef __alpha__ +TRUE +#else +FALSE; +#endif +; + + + +static bool +hw_clock_is_utc(const bool utc, const bool local_opt, + const struct adjtime adjtime) { +/*---------------------------------------------------------------------------- + Return true iff the hardware clock keeps Coordinated Universal Time + rather than local time. + + 'utc' means the user told us in the invocation options that the + hardware clock is kept in UTC. +-----------------------------------------------------------------------------*/ + + bool retval; /* our return value */ + + if (utc) retval = TRUE; + else if (local_opt) retval = FALSE; + else retval = (adjtime.local_utc == UTC); + if (debug) printf("Assuming hardware clock is kept in %s time.\n", + retval ? "UTC" : "LOCAL"); + return retval; +} + + + +static void +read_adjtime(struct adjtime *adjtime_p, int *rc_p) { +/*---------------------------------------------------------------------------- + Read the adjustment parameters and other persistent variables out of + the /etc/adjtime file. + + Return them as the adjtime structure <*adjtime_p>. + + If there is no /etc/adjtime file, return defaults. + If values are missing from the file, return defaults for them. + + return *rc_p = 0 if all OK, !=0 otherwise. + + Note: The default is LOCAL rather than UTC for historical reasons. + +-----------------------------------------------------------------------------*/ + FILE *adjfile; + int rc; /* local return code */ + struct stat statbuf; /* We don't even use the contents of this. */ + + rc = stat(ADJPATH, &statbuf); + if (rc < 0 && errno == ENOENT) { + /* He doesn't have a adjtime file, so we'll use defaults. */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + adjtime_p->local_utc = LOCAL; + + *rc_p = 0; + } else { + adjfile = fopen(ADJPATH, "r"); /* open file for reading */ + if (adjfile == NULL) { + const int fopen_errno = errno; + fprintf(stderr, MYNAME " is unable to open file " ADJPATH ". " + "fopen() errno=%d:%s", fopen_errno, strerror(fopen_errno)); + *rc_p = 2; + } else { + char line1[81]; /* String: first line of adjtime file */ + char line2[81]; /* String: second line of adjtime file */ + char line3[81]; /* String: third line of adjtime file */ + + line1[0] = '\0'; /* In case fgets fails */ + fgets(line1, sizeof(line1), adjfile); + line2[0] = '\0'; /* In case fgets fails */ + fgets(line2, sizeof(line2), adjfile); + line3[0] = '\0'; /* In case fgets fails */ + fgets(line3, sizeof(line3), adjfile); + + fclose(adjfile); + + /* Set defaults in case values are missing from file */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + adjtime_p->local_utc = LOCAL; + + sscanf(line1, "%f %d %f", + &adjtime_p->drift_factor, + (int *) &adjtime_p->last_adj_time, + &adjtime_p->not_adjusted); + + sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time); + + { + char local_utc_string[sizeof(line3)]; + + local_utc_string[0] = '\0'; /* In case nothing in line3 */ + sscanf(line3, "%s", local_utc_string); + + *rc_p = 0; /* Initial assumption - local/utc token is valid */ + if (strlen(local_utc_string) == 0) + adjtime_p->local_utc = LOCAL; + else if (strcmp(local_utc_string, "UTC") == 0) + adjtime_p->local_utc = UTC; + else if (strcmp(local_utc_string, "LOCAL") == 0) + adjtime_p->local_utc = LOCAL; + else { + fprintf(stderr, "%s: The first token of the third line of the file " + ADJPATH " is invalid. It must be LOCAL or UTC, indicating " + "to which time zone the hardware clock is set. Its " + "present value is '%s'.\n", MYNAME, local_utc_string); + *rc_p = 5; + } + } + } + adjtime_p->dirty = FALSE; + + if (debug) { + printf("Last drift adjustment done %s (Time %d)\n", + ctime2(adjtime_p->last_adj_time), + (int) adjtime_p->last_adj_time); + printf("Last calibration done %s (Time %d)\n", + ctime2(adjtime_p->last_calib_time), + (int) adjtime_p->last_calib_time); + } + } +} + + + +static void +synchronize_to_clock_tick(enum clock_access_method clock_access, + const int dev_port, const bool use_uf_bit, + int *retcode_p) { +/*----------------------------------------------------------------------------- + Wait until the moment the Hardware Clock updates to the next second, + so we know the exact time. + + The clock only has 1 second precision, so it gives the exact time only + once per second. + + Return *retcode_p == 0 if it worked, nonzero if it didn't. +-----------------------------------------------------------------------------*/ + if (debug) printf("Waiting for clock tick...\n"); + + switch (clock_access) { + case ISA: synchronize_to_clock_tick_ISA(retcode_p, -1, use_uf_bit); break; + case DEV_PORT: synchronize_to_clock_tick_ISA(retcode_p, dev_port, + use_uf_bit); break; + case RTC_IOCTL: synchronize_to_clock_tick_RTC(retcode_p); break; + case KD: synchronize_to_clock_tick_KD(retcode_p); break; + default: + fprintf(stderr, "%s: Internal error in synchronize_to_clock_tick. " + "Invalid value for clock_access argument: %d.\n", + MYNAME, clock_access); + *retcode_p = 1; + } + if (debug) printf("...got clock tick\n"); + return; +} + + +static struct tm +make_within_one_year(const struct tm base_tm, const time_t last_known_time) { +/*---------------------------------------------------------------------------- + Compute a time that is the same as the input base_tm, except for a + different year. The year shall be whatever year it takes to make the + output time within one year after last_known_time. + + The timezone for both the input and output values is the value of + the TZ environment variable. +-----------------------------------------------------------------------------*/ + struct tm broken_last_known_time; + /* The input time last_known_time, in broken down format */ + struct tm test_time; + + if (debug) + printf("Ignoring clock year and assuming " + "it's within 1 year after %s\n", + ctime2(last_known_time)); + + broken_last_known_time = *localtime(&last_known_time); + + test_time = base_tm; + test_time.tm_year = broken_last_known_time.tm_year; + + if (mktime(&test_time) < last_known_time) + test_time.tm_year += 1; + + return(test_time); +} + + + +static void +mktime_tz(struct tm hw_tm, const bool universal, const bool badyear, + const time_t last_known_time, + bool *valid_p, time_t *systime_p) { +/*----------------------------------------------------------------------------- + Convert a time in broken down format (hours, minutes, etc.) as read + from the Hardware Clock into standard 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. + + Argument 'badyear' true means the input time is from one of those + machines with the Award BIOS that is incapable of storing a year + value less than 94 or 95, which means we can't use the year value + from the clock (see documentation of hwclock's --badyear option). + In this case, we instead determine the year by assuming that it's + less than a year since the time . + + + 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 mktime_result; /* The value returned by our mktime() call */ + struct tm adjusted_tm; + /* The same as the value from our argument, except if we determine + the year in the argument is garbage, this value contains the year + computed from the ADJTIME file instead. + */ + char *zone; /* Local time zone name */ + + /* We use the C library function mktime(), but since it only works on + local time zone input, we may have to fake it out by temporarily + changing the local time zone to UTC. + */ + zone = (char *) getenv("TZ"); /* remember original time zone */ + + if (universal) { + /* Set timezone to UTC */ + setenv("TZ", "UTC 0", TRUE); + /* Note: tzset() gets called implicitly by the time code, but only the + first time. When changing the environment variable, better call + tzset() explicitly. + + Also: documentation for tzset() says if TZ = "", that means UTC. + But practice shows that that only works if tzset() hasn't already + been called before. So we explicitly say "UTC 0". + */ + tzset(); + } + + if (badyear) + adjusted_tm = make_within_one_year(hw_tm, last_known_time); + else adjusted_tm = hw_tm; + + mktime_result = mktime(&adjusted_tm); + if (mktime_result == -1) { + /* This apparently (not specified in mktime() documentation) means + the 'adjusted_tm' structure does not contain valid values (however, not + containing valid values does _not_ imply mktime() returns -1). + */ + /* Note that we are assuming here that the invalidity came from the + hardware values and was not introduced by our adjustments! + */ + *valid_p = FALSE; + *systime_p = 0; + if (debug) + printf("Invalid values in hardware clock: " + "%2d/%.2d/%.2d %.2d:%.2d:%.2d\n", + hw_tm.tm_year, hw_tm.tm_mon+1, hw_tm.tm_mday, + hw_tm.tm_hour, hw_tm.tm_min, hw_tm.tm_sec + ); + } else { + *valid_p = TRUE; + *systime_p = mktime_result; + if (debug) + printf("Hw clock time : %s = %d seconds since 1969\n", + ctime2(*systime_p), (int) *systime_p); + } + /* now put back the original zone. */ + if (zone) setenv("TZ", zone, TRUE); + else unsetenv("TZ"); + tzset(); +} + + + +static void +read_hardware_clock(const enum clock_access_method method, + const int dev_port, + const bool universal, const int hc_zero_year, + const bool badyear, + const time_t last_known_time, + bool *valid_p, time_t *systime_p) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via *systime_p + argument. + + If the hardware clock fails to tell us a time, return *valid_p == false + and undefined value as *systime_p. Otherwise *valid_p == true. + + Consider the hardware clock to be set in Coordinated Universal Time + (UTC) iff 'universal' == true. + + Consider the year value of the clock to be useless iff 'badyear' == true. + + Recognize that the present time is is after 'last_known_time', which + information may be necessary to interpret the value of some hardware + clocks. + + Use the method indicated by 'method' argument to access the hardware clock. +-----------------------------------------------------------------------------*/ + struct tm tm; + + switch (method) { + case RTC_IOCTL: + read_hardware_clock_rtc_ioctl(&tm); + break; + case ISA: + read_hardware_clock_isa(&tm, -1, hc_zero_year); + break; + case DEV_PORT: + read_hardware_clock_isa(&tm, dev_port, hc_zero_year); + break; + case KD: + read_hardware_clock_kd(&tm); + break; + default: + fprintf(stderr, + "%s: Internal error: invalid value for clock access method.\n", + MYNAME); + exit(5); + } + if (debug) + printf ("Time read from Hardware Clock: Y=%d M=%d D=%d %02d:%02d:%02d\n", + tm.tm_year, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + mktime_tz(tm, universal, badyear, last_known_time, valid_p, systime_p); +} + + + +static void +set_hardware_clock(const enum clock_access_method method, + const int dev_port, + const time_t newtime, + const bool universal, + const int hc_zero_year, const bool badyear, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time 'newtime', in local time zone or UTC, + according to 'universal'. + + 'badyear' true means the clock is incapable of storing the proper + year value, so we instead store 95, 96, 97, or 98 so that it is at + least in the right place in the leap year cycle (and will remain so + for at least the next year). + + Use the method indicated by the 'method' argument. +----------------------------------------------------------------------------*/ + struct tm new_broken_time; + /* Time to which we will set Hardware Clock, in broken down format, in + the time zone of caller's choice + */ + + if (universal) new_broken_time = *gmtime(&newtime); + else new_broken_time = *localtime(&newtime); + + /* If the clock is incapable of storing the true year value, change + the year to a fictional stand-in year as described in the prolog. + */ + if (badyear) + new_broken_time.tm_year = 95 + ((new_broken_time.tm_year + 1) % 4); + + if (debug) + printf("Setting Hardware Clock to %.2d:%.2d:%.2d " + "= %d seconds since 1969\n", + new_broken_time.tm_hour, new_broken_time.tm_min, + new_broken_time.tm_sec, (int) newtime); + + switch (method) { + case RTC_IOCTL: + set_hardware_clock_rtc_ioctl(new_broken_time, testing); + break; + case ISA: + set_hardware_clock_isa(new_broken_time, hc_zero_year, -1, testing); + break; + case DEV_PORT: + set_hardware_clock_isa(new_broken_time, hc_zero_year, dev_port, testing); + break; + case KD: + set_hardware_clock_kd(new_broken_time, testing); + break; + default: + fprintf(stderr, + "%s: Internal error: invalid value for clock access method.\n", + MYNAME); + exit(5); + } +} + + + +static void +set_hardware_clock_exact(const time_t settime, + const struct timeval ref_time, + const enum clock_access_method clock_access, + const int dev_port, + const bool universal, + const int hc_zero_year, + const bool badyear, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time 'settime', in local time zone or UTC, + according to 'universal'. + + But iff 'badyear', use a fictional year as appropriate for the --badyear + option. + + But correct 'settime' and wait for a fraction of a second so that + 'settime' is the value of the Hardware Clock as of system time + 'ref_time', which is in the past. For example, if 'settime' is + 14:03:05 and 'ref_time' is 12:10:04.5 and the current system + time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since + 'ref_time') and then set the Hardware Clock to 14:03:07, thus + getting a precise and retroactive setting of the clock. + + (Don't be confused by the fact that the system clock and the Hardware + Clock differ by two hours in the above example. That's just to remind + you that there are two independent time scales here). + + This function ought to be able to accept set times as fractional times. + Idea for future enhancement. + +-----------------------------------------------------------------------------*/ + time_t newtime; /* Time to which we will set Hardware Clock */ + struct timeval now_time; /* locally used time */ + + gettimeofday(&now_time, NULL); + newtime = settime + (int) time_diff(now_time, ref_time) + 1; + if (debug) + printf("Time elapsed since reference time has been %.6f seconds.\n" + "Delaying further to reach the next full second.\n", + time_diff(now_time, ref_time)); + + /* Now delay some more until Hardware Clock time 'newtime' arrives */ + do gettimeofday(&now_time, NULL); + while (time_diff(now_time, ref_time) < newtime - settime); + + set_hardware_clock(clock_access, dev_port, newtime, + universal, hc_zero_year, badyear, testing); +} + + + +static void +display_time(const bool hclock_valid, const time_t systime, + const float sync_duration, const bool badyear_warn) { +/*---------------------------------------------------------------------------- + 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'. + + If the year is 1994 or 1995 and 'badyear_warn' is true, warn the + user that he has a brain-damaged clock and needs to use --badyear. + Since we didn't exist in 1994 and 1995, we know the clock isn't + correct. + +-----------------------------------------------------------------------------*/ + if (!hclock_valid) + fprintf(stderr, "%s: 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", MYNAME); + else { + if (badyear_warn && (systime > START_OF_1994 && systime < END_OF_1995)) { + printf("WARNING: The Hardware Clock shows a time in 1994 " + "or 1995. This probably means you have a Hardware Clock " + "that is incapable of tracking years after 1999, and you " + "must use the --badyear option to make hwclock work for " + "you. See hwclock documentation for details.\n"); + } + + printf("%s %.6f seconds\n", ctime2(systime), -(sync_duration)); + } +} + + + +static int +interpret_date_string(const char *date_opt, time_t * const time_p) { +/*---------------------------------------------------------------------------- + Interpret the value of the --date option, which is something like + "13:05:01". In fact, it can be any of the myriad ASCII strings that specify + a time which the "date" program can understand. The date option value in + question is our "dateopt" argument. + + The specified time is in the local time zone. + + Our output, "*time_p", is a seconds-into-epoch time. + + We use the "date" program to interpret the date string. "date" must be + runnable by issuing the command "date" to the /bin/sh shell. That means + in must be in the current PATH. + + If anything goes wrong (and many things can), we return return code + 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p + is valid. +----------------------------------------------------------------------------*/ + FILE *date_child_fp; + char date_resp[100]; + const char magic[]="seconds-into-epoch="; + char date_command[100]; + int retcode; /* our eventual return code */ + int rc; /* local return code */ + + if (date_opt == NULL) { + fprintf(stderr, "%s: No --date option specified.\n", MYNAME); + retcode = 14; + } else if (strchr(date_opt, '"') != NULL) { + /* Quotation marks in date_opt would ruin the date command we construct. + */ + fprintf(stderr, "%s: The value of the --date option is not a valid date.\n" + "In particular, it contains quotation marks.\n", MYNAME); + retcode = 12; + } else { + sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s", + date_opt); + if (debug) printf("Issuing date command: %s\n", date_command); + + date_child_fp = popen(date_command, "r"); + if (date_child_fp == NULL) { + fprintf(stderr, "%s: Unable to run 'date' program in /bin/sh shell. " + "popen() failed with errno=%s (%d)\n", + MYNAME, strerror(errno), errno); + retcode = 10; + } else { + date_resp[0] = '\0'; /* in case fgets fails */ + fgets(date_resp, sizeof(date_resp), date_child_fp); + if (debug) printf("response from date command = %s\n", date_resp); + if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) { + fprintf(stderr, "%s: The date command issued by " MYNAME " returned " + "unexpected results.\n" + "The command was:\n %s\nThe response was:\n %s\n", + MYNAME, date_command, date_resp); + retcode = 8; + } else { + int seconds_since_epoch; + rc = sscanf(date_resp + sizeof(magic)-1, "%d", &seconds_since_epoch); + if (rc < 1) { + fprintf(stderr, "%s: The date command issued by " MYNAME " returned" + "something other than an integer where the converted" + "time value was expected.\n" + "The command was:\n %s\nThe response was:\n %s\n", + MYNAME, date_command, date_resp); + retcode = 6; + } else { + retcode = 0; + *time_p = seconds_since_epoch; + if (debug) + printf("date string %s equates to %d seconds since 1969.\n", + date_opt, (int) *time_p); + } + } + fclose(date_child_fp); + } + } + return(retcode); +} + + + +static int +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. + + 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 */ + + if (!hclock_valid) { + fprintf(stderr, "%s: The Hardware Clock does not contain a valid time, so " + "we cannot set the System Time from it.\n", MYNAME); + retcode = 1; + } else { + 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" ); + /* Note: tv_sec and tv_usec are declared variously on different + systems: int, long, time_t. Casting to long below makes it + compile everywhere. + */ + 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() see, in addition to its man page, + 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, "%s: Must be superuser to set system clock.\n", + MYNAME); + else + fprintf(stderr, + "%s: settimeofday() failed, errno=%s (%d)\n", + MYNAME, strerror(errno), errno); + retcode = 1; + } else retcode = 0; + } + } + return(retcode); +} + + +static void +adjust_drift_factor(struct adjtime *adjtime_p, + const time_t actual_time, + const bool hclock_valid, + const struct timeval hclocktime ) { +/*--------------------------------------------------------------------------- + Update the drift factor and calibration parameters in '*adjtime_p' + to reflect the fact that at some recent instant when the actual time + was 'actual_time', the Hardware Clock said the time was + 'hclocktime', and that we have corrected the Hardware Clock + accordingly. Note that 'hclocktime' is a fractional time, taking + into consideration the Hardware Clock register contents and how long + those contents had been that. + + We assume that the only cause of error in the Hardware Clock is + systematic drift and that the user has been doing regular drift + adjustments using the drift factor in the adjtime file. Therefore, + if 'actual_time' and 'hclocktime' are different, that means the drift + factor isn't quite right. + + EXCEPT: if 'hclock_valid' 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. + + Also, don't adjust if the error is more than 30 minutes, because that + kind of error probably isn't drift. + +----------------------------------------------------------------------------*/ + if (!hclock_valid) { + if (debug) + printf("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n"); + } else if (adjtime_p->last_calib_time == 0) { + if (debug) + printf("Not adjusting drift factor because there is no \n" + "previous calibration information (i.e. adjtime file is \n" + "nonexistent or has 0 in last calibration time field).\n"); + } else if (time_diff(hclocktime, t2tv(adjtime_p->last_calib_time)) + < 23.0 * 60.0 * 60.0) { + if (debug) + printf("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n"); + } else { + const float sec_per_day = 24.0 * 60.0 * 60.0; + float atime_per_htime; /* adjusted time units per hardware time unit */ + float adj_days; /* days since last adjustment (in hardware clock time) */ + float cal_days; /* days since last calibration (in hardware clock time) */ + float exp_drift; /* expected drift (sec) since last adjustment */ + float unc_drift; /* uncorrected drift (sec) since last calibration */ + float factor_adjust; /* amount to add to previous drift factor */ + atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day; + adj_days = time_diff(hclocktime, t2tv(adjtime_p->last_adj_time)) + / sec_per_day; + exp_drift = adj_days * adjtime_p->drift_factor + adjtime_p->not_adjusted; + unc_drift = time_diff(t2tv(actual_time), hclocktime) - exp_drift; + cal_days = ((float)(adjtime_p->last_adj_time - adjtime_p->last_calib_time) + + adjtime_p->not_adjusted) / (sec_per_day * atime_per_htime) + + adj_days; + factor_adjust = unc_drift / cal_days; + + if (unc_drift > 30*60.0) { + if (debug) + printf("Not adjusting drift factor because we calculated the \n" + "uncorrected drift as %.0f seconds, which is so large that \n" + "it probably is not drift at all, but rather some \n" + "clock setting anomaly.\n\n", unc_drift); + } else { + if (debug) + printf("Clock drifted %.1f seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n", + unc_drift, + (int) (actual_time - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } + } + adjtime_p->last_calib_time = actual_time; + + adjtime_p->last_adj_time = actual_time; + + adjtime_p->not_adjusted = 0; + + adjtime_p->dirty = TRUE; +} + + + +static void +calculate_adjustment( + const float factor, + const time_t last_time, + const float not_adjusted, + const time_t systime, + int *adjustment_p, + float *retro_p, + const int debug ) { +/*---------------------------------------------------------------------------- + Do the drift adjustment calculation. + + The way we have to set the clock, we need the adjustment in two parts: + + 1) an integer number of seconds (return as *adjustment_p) + + 2) a positive fraction of a second (less than 1) (return as *retro_p) + + The sum of these two values is the adjustment needed. Positive means to + advance the clock or insert seconds. Negative means to retard the clock + or remove seconds. +----------------------------------------------------------------------------*/ + float exact_adjustment; + + exact_adjustment = ((float) (systime - last_time)) * factor / (24 * 60 * 60) + + not_adjusted; + *adjustment_p = FLOOR(exact_adjustment); + + *retro_p = exact_adjustment - (float) *adjustment_p; + if (debug) { + printf ("Time since last adjustment is %d seconds\n", + (int) (systime - last_time)); + printf ("Need to insert %d seconds and refer time back " + "%.6f seconds ago\n", + *adjustment_p, *retro_p); + } +} + + + +static void +save_adjtime(const struct adjtime adjtime, const bool testing) { +/*----------------------------------------------------------------------------- + Write the contents of the structure to its disk file. + + But if the contents are clean (unchanged since read from disk), don't + bother. +-----------------------------------------------------------------------------*/ + char newfile[506]; /* Stuff to write to disk file */ + /* snprintf is not always available, but this is safe + as long as libc does not use more than 100 positions for %ld or %f + */ + + int rc; /* locally used: return code from a function */ + + if (adjtime.dirty) { + /* We'd use snprintf here, but apparently, it isn't always available. */ + sprintf(newfile, "%f %ld %f\n%ld\n%s\n", + adjtime.drift_factor, + (long) adjtime.last_adj_time, + adjtime.not_adjusted, + (long) adjtime.last_calib_time, + (adjtime.local_utc == UTC) ? "UTC" : "LOCAL" + ); + + if (testing) { + printf("Not updating adjtime file because of testing mode.\n"); + printf("Would have written the following to %s:\n%s", + ADJPATH, newfile); + } else { + FILE *adjfile; + + adjfile = fopen(ADJPATH, "w"); + if (adjfile == NULL) { + const int fopen_errno = errno; + printf("Could not open file with the clock adjustment parameters " + "in it (%s) for output.\n" + "fopen() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fopen_errno, strerror(errno)); + } else { + rc = fprintf(adjfile, newfile); + if (rc < 0) { + const int fprintf_errno = errno; + printf("Could not update file (%s) " + "with the clock adjustment parameters in it.\n" + "fprintf() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fprintf_errno, strerror(errno)); + } + rc = fclose(adjfile); + if (rc < 0) { + const int fclose_errno = errno; + printf("Could not update file (%s) " + "with the clock adjustment parameters in it.\n" + "fclose() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fclose_errno, strerror(errno)); + } + } + } + } else if (debug) + printf("Skipping update of adjtime file because nothing has changed.\n"); +} + + + +static void +do_adjustment(struct adjtime *adjtime_p, + const bool hclock_valid, const time_t hclocktime, + const struct timeval read_time, + const enum clock_access_method clock_access, + const int dev_port, const bool universal, + const int hc_zero_year, + const bool badyear, const bool testing) { +/*--------------------------------------------------------------------------- + Do the adjustment requested, by 1) setting the Hardware Clock (if + 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 'factor' and 'last_time' are current values from the adjtime + file. + + 'hclock_valid' means the Hardware Clock contains a valid time, and that + time is 'hclocktime'. + + 'read_time' is the current system time (to be precise, it is the system + time at the time 'hclocktime' was read, which due to computational delay + could be a short time ago). + + 'universal': the Hardware Clock is kept in UTC. + + 'badyear': the Hardware Clock is incapable of storing years outside + the range 1994-1999. + + 'testing': We are running in test mode (no updating of clock). + + We do not bother to update the clock if the adjustment would be less than + one second. This is to avoid cumulative error and needless CPU hogging + (remember we use an infinite loop for some timing) if the user runs us + frequently. + +----------------------------------------------------------------------------*/ + if (!hclock_valid) { + fprintf(stderr, "%s: The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n", MYNAME); + /* Any previous calibration had to be before the clock got hosed, so + wipe out the record of it so it won't be used in the future. + */ + adjtime_p->last_calib_time = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->dirty = TRUE; + } else if (adjtime_p->last_adj_time == 0) { + if (debug) + printf("Not adjusting clock because we have no information about \n" + "the previous calibration (i.e. the adjtime file is \n" + "nonexistent or contains zero in the last calibrated time \n" + "field).\n"); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ + 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, dev_port, universal, + hc_zero_year, badyear, 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"); + } +} + + +static void +determine_clock_access_method(const bool user_requests_ISA, + const bool user_says_jensen, + enum clock_access_method *clock_access_p) { +/*---------------------------------------------------------------------------- + Figure out how we're going to access the hardware clock, by seeing + what facilities are available, looking at invocation options, and + using compile-time constants. + + 'user_requests_ISA' means the user explicitly asked for the ISA method, + so we'll use that (even if we know it will fail because the machine + is incapable!). +-----------------------------------------------------------------------------*/ + const bool jensen = + user_says_jensen || + (alpha_machine && is_in_cpuinfo("system type", "Jensen")); + /* See comments at top of program for how Jensen is a special case. */ + bool rtc_works; + /* The /dev/rtc method is available and seems to work on this machine */ + bool kdghwclk_works; + /* The KDHWCLK method is available and seems to work on this machine. */ + + see_if_rtc_works(&rtc_works); /* May issue error messages */ + see_if_kdghwclk_works(&kdghwclk_works); /* May issue error messages */ + + if (user_requests_ISA) *clock_access_p = ISA; + else if (rtc_works) *clock_access_p = RTC_IOCTL; + else if (kdghwclk_works) *clock_access_p = KD; + else if (got_kdghwclk) *clock_access_p = ISA; + /* I don't know on what machine the above line makes any sense, but the + code has always been this way. -BJH 99.03.31 + */ + else if (isa_machine) *clock_access_p = ISA; + else if (jensen) *clock_access_p = DEV_PORT; + else if (alpha_machine) *clock_access_p = ISA; + else *clock_access_p = NOCLOCK; + if (debug) { + switch (*clock_access_p) { + case ISA: printf("Using direct I/O instructions to ISA clock.\n"); break; + case KD: printf("Using KDGHWCLK interface to m68k clock.\n"); break; + case RTC_IOCTL: printf("Using /dev/rtc interface to clock.\n"); break; + case DEV_PORT: printf("Using /dev/port interface to clock.\n"); break; + case NOCLOCK: printf("Unable to find a usable clock access method.\n"); + break; + default: + printf("determine_clock_access_method() returned invalid value: %d.\n", + *clock_access_p); + } + } +} + + + +static void +do_systohc(const enum clock_access_method clock_access, + const int dev_port, + const time_t hclocktime, const bool hclock_valid, + const struct timeval read_time, + const bool universal, const int hc_zero_year, + const bool badyear, const bool testing, + struct adjtime * const adjtime_p) { +/*---------------------------------------------------------------------------- + Perform the specifics of the hwclock --systohc function. +-----------------------------------------------------------------------------*/ + struct timeval nowtime, reftime; + /* We can only set_hardware_clock_exact to a whole seconds + time, so we set it with reference to the most recent + whole seconds time. + */ + gettimeofday(&nowtime, NULL); + reftime.tv_sec = nowtime.tv_sec; + reftime.tv_usec = 0; + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + clock_access, dev_port, universal, + hc_zero_year, badyear, testing); + adjust_drift_factor(adjtime_p, (time_t) reftime.tv_sec, hclock_valid, + time_inc(t2tv(hclocktime), + - time_diff(read_time, reftime) + ) + ); +} + + +static void +manipulate_clock(const bool show, const bool adjust, + const bool set, const time_t set_time, + const bool hctosys, const bool systohc, + const struct timeval startup_time, + const enum clock_access_method clock_access, + const bool utc, const bool local_opt, + const bool badyear, const bool arc_opt, const bool srm_opt, + const bool user_wants_uf, + const bool testing, + int *retcode_p + ) { +/*--------------------------------------------------------------------------- + Do all the normal work of hwclock - read, set clock, etc. + + Issue output to stdout and error message to stderr where appropriate. + + Return rc == 0 if everything went OK, rc != 0 if not. +----------------------------------------------------------------------------*/ + struct adjtime adjtime; + /* Contents of the adjtime file, or what they should be. */ + int rc; /* local return code */ + bool no_auth; /* User lacks necessary authorization to access the clock */ + int dev_port; + /* File descriptor for /dev/port, if we're using it. -1 if we + couldn't open it. 0 if we aren't using it. + */ + get_inb_outb_privilege(clock_access, &no_auth); + + if (no_auth) *retcode_p = 1; + else { + get_dev_port_access(clock_access, &dev_port); + + if (dev_port < 0) *retcode_p = 3; + else { + read_adjtime(&adjtime, &rc); + if (rc != 0) *retcode_p = 2; + else { + const bool use_uf_bit = uf_bit_needed(user_wants_uf); + const int hc_zero_year = zero_year(arc_opt, srm_opt); + /* year of century to which a value of zero corresponds in the + Hardware Clock's year register. + */ + const bool universal = hw_clock_is_utc(utc, local_opt, adjtime); + /* The hardware clock is kept in Coordinated Universal Time. */ + + if ((set || systohc || adjust) && + (adjtime.local_utc == UTC) != universal) { + adjtime.local_utc = universal ? UTC : LOCAL; + adjtime.dirty = TRUE; + } + + synchronize_to_clock_tick(clock_access, dev_port, use_uf_bit, + retcode_p); + /* this takes up to 1 second */ + if (*retcode_p == 0) { + 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, dev_port, universal, + hc_zero_year, badyear, + adjtime.last_calib_time, + &hclock_valid, &hclocktime); + + if (show) { + display_time(hclock_valid, hclocktime, + time_diff(read_time, startup_time), !badyear); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + clock_access, dev_port, universal, + hc_zero_year, + badyear, testing); + adjust_drift_factor(&adjtime, set_time, hclock_valid, + time_inc(t2tv(hclocktime), + - time_diff(read_time, startup_time) + ) + ); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, clock_access, dev_port, + universal, hc_zero_year, + badyear, testing); + *retcode_p = 0; + } else if (systohc) { + do_systohc(clock_access, dev_port, + hclocktime, hclock_valid, read_time, + universal, hc_zero_year, badyear, testing, + &adjtime); + *retcode_p = 0; + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode_p = 1; + } else *retcode_p = 0; + } + save_adjtime(adjtime, testing); + } + } + } + if (clock_access == DEV_PORT && dev_port >= 0) close(dev_port); + } +} + + + +static void +report_version(void) { + + char *additional_version; /* malloc'ed */ + /* Stuff to add on to the version report, after the basic version. + If this is hwclock packaged with util-linux, this is the + util-linux version. Otherwise, it's nothing. + */ + +#ifdef UTIL_LINUX + additional_version = malloc(strlen(util_linux_version) + 5); + sprintf(additional_version, "/%s", util_linux_version); +#else + additional_version = strdup(""); +#endif + printf(MYNAME " " VERSION "%s\n", additional_version); + free(additional_version); +} + + + +static void +manipulate_epoch(const bool getepoch, const bool setepoch, + const int epoch_opt, const bool testing) { +/*---------------------------------------------------------------------------- + Get or set the Hardware Clock epoch value in the kernel, as appropriate. + 'getepoch', 'setepoch', and 'epoch' are hwclock invocation options. + + 'epoch' == -1 if the user did not specify an "epoch" option. + +-----------------------------------------------------------------------------*/ + /* + Maintenance note: This should work on non-Alpha machines, but the + evidence today (98.03.04) indicates that the kernel only keeps the + epoch value on Alphas. If that is ever fixed, this function should be + changed. + */ + + if (!alpha_machine) + fprintf(stderr, + "%s: The kernel keeps an epoch value for the Hardware Clock " + "only on an Alpha machine.\nThis copy of hwclock was built for " + "a machine other than Alpha\n(and thus is presumably not running " + "on an Alpha now). No action taken.\n", MYNAME); + else { + if (getepoch) { + unsigned long epoch; + char *reason; /* malloc'ed */ + + get_epoch(&epoch, &reason); + if (reason != NULL) { + printf("Unable to get the epoch value from the kernel. %s\n", + reason); + free(reason); + } else + printf("Kernel is assuming an epoch value of %lu\n", epoch); + } else if (setepoch) { + if (epoch_opt == -1) + fprintf(stderr, "%s: To set the epoch value, you must use the 'epoch' " + "option to tell to what value to set it.\n", MYNAME); + else { + int rc; + set_epoch(epoch_opt, testing, &rc); + if (rc != 0) + printf("Unable to set the epoch value in the kernel.\n"); + } + } + } +} + + + +int +main(int argc, char **argv, char **envp) { +/*---------------------------------------------------------------------------- + MAIN +-----------------------------------------------------------------------------*/ + struct timeval startup_time; + /* The time we started up, in seconds into the epoch, including fractions. + */ + time_t set_time; /* Time to which user said to set Hardware Clock */ + + enum clock_access_method clock_access; + /* The method that we determine is best for accessing Hardware Clock + on this system. + */ + + bool permitted; /* User is permitted to do the function */ + int retcode; /* Our eventual return code */ + + int rc; /* local return code */ + + /* option_def is the control table for the option parser. These other + variables are the results of parsing the options and their meanings + are given by the option_def. The only exception is , which + may be modified after parsing is complete to effect an implied option. + */ + bool show, set, systohc, hctosys, adjust, getepoch, setepoch, version; + bool utc, local_opt, badyear, testing, directisa; + bool arc_opt, jensen_opt, srm_opt, funky_opt; + char *date_opt; + int epoch_opt; + + const optStruct option_def[] = { + { 'r', (char *) "show", OPT_FLAG, &show, 0 }, + { 0, (char *) "set", OPT_FLAG, &set, 0 }, + { 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 }, + { 's', (char *) "hctosys", OPT_FLAG, &hctosys, 0 }, + { 0, (char *) "getepoch", OPT_FLAG, &getepoch, 0 }, + { 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 }, + { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 }, + { 'v', (char *) "version", OPT_FLAG, &version, 0 }, + { 0, (char *) "date", OPT_STRING, &date_opt, 0 }, + { 0, (char *) "epoch", OPT_UINT, &epoch_opt, 0 }, + { 'u', (char *) "utc", OPT_FLAG, &utc, 0 }, + { 0, (char *) "localtime", OPT_FLAG, &local_opt, 0 }, + { 0, (char *) "badyear", OPT_FLAG, &badyear, 0 }, + { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 }, + { 0, (char *) "test", OPT_FLAG, &testing, 0 }, + { 'D', (char *) "debug", OPT_FLAG, &debug, 0 }, + { 'A', (char *) "arc", OPT_FLAG, &arc_opt, 0 }, + { 'J', (char *) "jensen", OPT_FLAG, &jensen_opt,0 }, + { 'S', (char *) "srm", OPT_FLAG, &srm_opt, 0 }, + { 'F', (char *) "funky-toy", OPT_FLAG, &funky_opt, 0 }, + { 0, (char *) NULL, OPT_END, NULL, 0 } + }; + int argc_parse; /* argc, except we modify it as we parse */ + char **argv_parse; /* argv, except we modify it as we parse */ + + assume_interrupts_enabled(); /* Since we haven't messed with them yet */ + + gettimeofday(&startup_time, NULL); /* Remember what time we were invoked */ + + /* set option defaults */ + show = set = systohc = hctosys = adjust = getepoch = setepoch = + version = utc = local_opt = badyear = + directisa = testing = debug = + jensen_opt = arc_opt = srm_opt = funky_opt = FALSE; + date_opt = NULL; + epoch_opt = -1; + + argc_parse = argc; argv_parse = argv; + optParseOptions(&argc_parse, argv_parse, option_def, 0); + /* Uses and sets argc_parse, argv_parse. + Sets show, set, systohc, hctosys, adjust, getepoch, setepoch, + version, utc, localtime, badyear, + directisa, testing, debug, + date_opt, epoch_opt, + jensen_opt, arc_opt, srm_opt, funky_opt + */ + + if (argc_parse - 1 > 0) { + fprintf(stderr, MYNAME " takes no non-option arguments. " + "You supplied %d. See man page for complete syntax.\n", + argc_parse - 1); + exit(100); + } + + if (show + set + systohc + hctosys + adjust + + getepoch + setepoch + version > 1) { + fprintf(stderr, + "You have specified multiple function options to hwclock.\n" + "You can only perform one function at a time.\n"); + exit(100); + } + + if (set) { + rc = interpret_date_string(date_opt, &set_time); /* (time-consuming) */ + if (rc != 0) { + fprintf(stderr, "%s: No usable set-to time given. Cannot set clock.\n", + MYNAME); + exit(100); + } + } + + if (jensen_opt && !alpha_machine) { + fprintf(stderr, "%s: Your options indicate that this is a Jensen model of " + "DEC Alpha, but this is not an Alpha machine!\n", MYNAME); + exit(100); + } + + if (srm_opt && alpha_machine) { + fprintf(stderr, "%s: Your options indicate that this machine keeps SRM " + "console time, but only DEC Alphas have such a clock and this is " + "not an Alpha!\n", MYNAME); + exit(100); + } + if (arc_opt && alpha_machine) { + fprintf(stderr, "%s: Your options indicate that this machine's clock" + "keeps ARC console time, " + "but only DEC Alphas have such a clock and this is " + "not an Alpha!\n", MYNAME); + exit(100); + } + + if (directisa && !(isa_machine || alpha_machine)) { + fprintf(stderr, "%s: You have requested direct access to the ISA Hardware " + "Clock using machine instructions from the user process. " + "But this method only works on an ISA machine with an x86 " + "CPU, or a similar machine such as DEC Alpha. " + "This is not one.\n", MYNAME); + exit(100); + } + + if (utc && local_opt) { + fprintf(stderr, "%s: The --utc and --localtime options are mutually " + "exclusive. You specified both.\n", MYNAME); + exit(100); + } + + + if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch | + version)) + show = TRUE; /* default to show */ + + + if (getuid() == 0) permitted = TRUE; + else { + /* program is designed to run setuid (in some situations) -- be secure! */ + if (set || hctosys || systohc || adjust) { + fprintf(stderr, + "%s: Sorry, only the superuser can change the " + "Hardware Clock.\n", MYNAME); + permitted = FALSE; + } else if (setepoch) { + fprintf(stderr, + "%s: Sorry, only the superuser can change " + "the Hardware Clock epoch in the kernel.\n", MYNAME); + permitted = FALSE; + } else permitted = TRUE; + } + + if (!permitted) retcode = 2; + else { + retcode = 0; + if (version) { + report_version(); + } else if (getepoch || setepoch) { + manipulate_epoch(getepoch, setepoch, epoch_opt, testing); + } else { + determine_clock_access_method(directisa, jensen_opt, &clock_access); + if (clock_access == NOCLOCK) + fprintf(stderr, "%s: Cannot access the Hardware Clock via any known " + "method. Use --debug option to see the details of our " + "search for an access method.\n", MYNAME); + else + manipulate_clock(show, adjust, set, set_time, hctosys, systohc, + startup_time, clock_access, utc, local_opt, badyear, + arc_opt, srm_opt, funky_opt, testing, &rc); + } + } + exit(retcode); +} + + +/**************************************************************************** + + History of this program: + + 99.04.08 BJH Version 2.5 + + Make it work on Alphas without /dev/rtc. Thanks to David Mosberger + , Jay Estabrook , + Martin Ostermann , Andries Brouwer + . Most of this code is lifted from another program + called "clock" (not the original ancestor of hwclock) that has + circulated for use on Alpha. + + Make it work on Sparc. + + Add --badyear option. Thanks to David J Coffin (dcoffin@shore.net) + for the design of this. + + Add --localtime option, local/UTC value in adjtime file, and defaults + for local/utc. + + Don't set CMOS memory Byte 50 (century byte). On some machines, + that byte not only isn't used as a century byte, but it is used for + something else. + + Don't update the drift factor if the variation is so huge that it + probably wasn't due to drift. + + Compute drift factor with better precision. + + 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. + + Fix some word length things so it works on Alpha. + + Make it work when /dev/rtc doesn't have the interrupt functions. + In this case, busywait for the top of a second instead of blocking and + waiting for the update complete interrupt. + + Fix a bunch of bugs too numerous to mention. + + 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte + 50) of the ISA Hardware Clock when using direct ISA I/O. Problem + discovered by job (jei@iclnl.icl.nl). + + Use the rtc clock access method in preference to the KDGHWCLK method. + Problem discovered by Andreas Schwab . + + November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt + (janl@math.uio.no) to make it compile on linux 1.2 machines as well + as more recent versions of the kernel. Introduced the NO_CLOCK + access method and wrote feature test code to detect absense of rtc + headers. + + + Bryan Henderson based hwclock on the program "clock", in September + 1996. While remaining mostly backward compatible with clock, + hwclock added the following: + + - You can set the hardware clock without also modifying the Linux + system clock. + + - You can read and set the clock with finer than 1 second precision. + + - When you set the clock, hwclock automatically refigures the drift + rate, based on how far off the clock was before you set it. (This + is the drift rate that is used with the --adjust function to + automatically adjust the clock periodically to compensate for drift). + + - More mnemonic GNU-style command line options. + + - Comments describing how the clock and program work to improve + maintainability. + + - Removed the old dead I/O code that worked without the inb/outb + instructions and without the asm/io.h definitions. + + The first version of hwclock was Version 2. + + Here is the history section from the "clock" program at the time it was + used as a basis for hwclock: + + V1.0 + + + V1.0 by Charles Hedrick, hedrick@cs.rutgers.edu, April 1992. + + ******************** + V1.1 + Modified for clock adjustments - Rob Hooft, hooft@chem.ruu.nl, Nov 1992 + Also moved error messages to stderr. The program now uses getopt. + Changed some exit codes. Made 'gcc 2.3 -Wall' happy. + + ***** + V1.2 + + Applied patches by Harald Koenig (koenig@nova.tat.physik.uni-tuebingen.de) + Patched and indented by Rob Hooft (hooft@EMBL-Heidelberg.DE) + + A free quote from a MAIL-message (with spelling corrections): + + "I found the explanation and solution for the CMOS reading 0xff problem + in the 0.99pl13c (ALPHA) kernel: the RTC goes offline for a small amount + of time for updating. Solution is included in the kernel source + (linux/kernel/time.c)." + + "I modified clock.c to fix this problem and added an option (now default, + look for USE_INLINE_ASM_IO) that I/O instructions are used as inline + code and not via /dev/port (still possible via #undef ...)." + + With the new code, which is partially taken from the kernel sources, + the CMOS clock handling looks much more "official". + Thanks Harald (and Torsten for the kernel code)! + + ***** + V1.3 + Canges from alan@spri.levels.unisa.edu.au (Alan Modra): + a) Fix a few typos in comments and remove reference to making + clock -u a cron job. The kernel adjusts cmos time every 11 + minutes - see kernel/sched.c and kernel/time.c set_rtc_mmss(). + This means we should really have a cron job updating + /etc/adjtime every 11 mins (set last_time to the current time + and not_adjusted to ???). + b) Swapped arguments of outb() to agree with asm/io.h macro of the + same name. Use outb() from asm/io.h as it's slightly better. + c) Changed CMOS_READ and CMOS_WRITE to inline functions. Inserted + cli()..sti() pairs in appropriate places to prevent possible + errors, and changed ioperm() call to iopl() to allow cli. + d) Moved some variables around to localise them a bit. + e) Fixed bug with clock -ua or clock -us that cleared environment + variable TZ. This fix also cured the annoying display of bogus + day of week on a number of machines. (Use mktime(), ctime() + rather than asctime() ) + f) Use settimeofday() rather than stime(). This one is important + as it sets the kernel's timezone offset, which is returned by + gettimeofday(), and used for display of MSDOS and OS2 file + times. + g) faith@cs.unc.edu added -D flag for debugging + + V1.4: alan@SPRI.Levels.UniSA.Edu.Au (Alan Modra) + Wed Feb 8 12:29:08 1995, fix for years > 2000. + faith@cs.unc.edu added -v option to print version. */ + + diff --git a/clockB/hwclock.h b/clockB/hwclock.h new file mode 100644 index 00000000..6a3ab14b --- /dev/null +++ b/clockB/hwclock.h @@ -0,0 +1,139 @@ +#include +#include +#include + +typedef int bool; +#define TRUE 1 +#define FALSE 0 + +#define MYNAME "hwclock" +#define VERSION "2.5" + + +enum clock_access_method {ISA, RTC_IOCTL, KD, DEV_PORT, NOCLOCK}; + /* A method for accessing (reading, writing) the hardware clock: + + ISA: + via direct CPU I/O instructions that work on an ISA family + machine (IBM PC compatible) or most DEC Alphas, which implement + enough of ISA to get by. + + RTC_IOCTL: + via the rtc device driver, using device special file /dev/rtc. + + KD: + via the console driver, using device special file /dev/tty1. + This is the m68k ioctl interface, known as KDGHWCLK. + + DEV_PORT: + via the /dev/port device, which is almost the same thing as + direct I/O instructions via the ISA method, but works on a Jensen + model of Alpha, whereas ISA does not. Also, use I/O addresses + 0x170 and 0x171 instead of the ISA 0x70 and 0x71. + + NO_CLOCK: + Unable to determine a usable access method for the system clock. + */ + + + + +/* hwclock.c */ +extern int debug; +extern const bool alpha_machine; +extern const bool isa_machine; + +/* directio.c */ + +extern void +assume_interrupts_enabled(void); + +extern void +synchronize_to_clock_tick_ISA(int *retcode_p, const int dev_port, + const bool use_uf_bit); + +extern void +read_hardware_clock_isa(struct tm *tm, const int dev_port, + int hc_zero_year); + +extern void +set_hardware_clock_isa(const struct tm new_tm, + const int hc_zero_year, + const int dev_port, + const bool testing); + +extern void +get_inb_outb_privilege(const enum clock_access_method clock_access, + bool * const no_auth_p); + +extern void +get_dev_port_access(const enum clock_access_method clock_access, + int * dev_port_p); + +extern bool +uf_bit_needed(const bool user_wants_uf); + +extern int +zero_year(const bool arc_opt, const bool srm_opt); + + +/* rtc.c */ +extern void +synchronize_to_clock_tick_RTC(int *retcode_p); + +extern void +read_hardware_clock_rtc_ioctl(struct tm *tm); + +extern void +set_hardware_clock_rtc_ioctl(const struct tm new_broken_time, + const bool testing); +extern void +see_if_rtc_works(bool * const rtc_works_p); + +extern void +get_epoch(unsigned long *epoch_p, char **reason_p); + +extern void +set_epoch(unsigned long epoch, const bool testing, int *retcode_p); + + +/* kd.c */ + +extern void +synchronize_to_clock_tick_KD(int *retcode_p); + +extern void +read_hardware_clock_kd(struct tm *tm); + +extern void +set_hardware_clock_kd(const struct tm new_broken_time, + const bool testing); + +extern void +see_if_kdghwclk_works(bool * const kdghwclk_works_p); + +extern const bool got_kdghwclk; + +/* util.c */ +extern bool +is_in_cpuinfo(const char * const fmt, const char * const str); + +extern char * +ctime2(const time_t time); + +extern struct timeval +t2tv(time_t argument); + +extern struct timeval +t2tv(time_t argument); + +extern float +time_diff(struct timeval subtrahend, struct timeval subtractor); + +extern struct timeval +time_inc(struct timeval addend, float increment); + + + + + diff --git a/clockB/kd.c b/clockB/kd.c new file mode 100644 index 00000000..68287cb5 --- /dev/null +++ b/clockB/kd.c @@ -0,0 +1,219 @@ +/************************************************************************** + + This is a component of the hwclock program. + + This file contains the code for accessing the hardware clock via + the KDHWCLK facility of M68k machines. + +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "hwclock.h" + + + +#if defined(KDGHWCLK) +const bool got_kdghwclk = TRUE; +static const int kdghwclk_ioctl = KDGHWCLK; +static const int kdshwclk_ioctl = KDSHWCLK; +#else +const bool got_kdghwclk = FALSE; +static const int kdghwclk_ioctl; /* Never used; just to make compile work */ +struct hwclk_time {int sec;}; + /* Never used; just to make compile work */ +#endif + + +void +synchronize_to_clock_tick_KD(int *retcode_p) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + int con_fd; + + if (debug) + printf("Waiting in loop for time from KDGHWCLK to change\n"); + + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd < 0) { + fprintf(stderr, "%s: open() failed to open /dev/tty1, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else { + int rc; /* return code from ioctl() */ + int i; /* local loop index */ + /* The time when we were called (and started waiting) */ + struct hwclk_time start_time, nowtime; + + rc = ioctl(con_fd, kdghwclk_ioctl, &start_time); + if (rc == -1) { + fprintf(stderr, "%s: KDGHWCLK to read time failed, " + "errno = %s (%d).\n", MYNAME, strerror(errno), errno); + *retcode_p = 3; + } + + for (i = 0; + (rc = ioctl(con_fd, kdghwclk_ioctl, &nowtime)) != -1 + && start_time.sec == nowtime.sec && i < 1000000; + i++); + if (i >= 1000000) { + fprintf(stderr, "%s: Timed out waiting for time change.\n", MYNAME); + *retcode_p = 2; + } else if (rc == -1) { + fprintf(stderr, "%s: KDGHWCLK to read time failed, " + "errno = %s (%d).\n", MYNAME, strerror(errno), errno); + *retcode_p = 3; + } else *retcode_p = 0; + close(con_fd); + } +} + + + +void +read_hardware_clock_kd(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to /dev/tty1 on what we assume is an m68k + machine. + + Note that we don't use /dev/console here. That might be a serial + console. +-----------------------------------------------------------------------------*/ +#ifdef KDGHWCLK + int con_fd; + struct hwclk_time t; + + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd < 0) { + fprintf(stderr, "%s: open() failed to open /dev/tty1, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + exit(5); + } else { + int rc; /* return code from ioctl() */ + + rc = ioctl(con_fd, kdghwclk_ioctl, &t); + if (rc == -1) { + fprintf(stderr, "%s: ioctl() failed to read time from /dev/tty1, " + "errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + exit(5); + } + close(con_fd); + } + + tm->tm_sec = t.sec; + tm->tm_min = t.min; + tm->tm_hour = t.hour; + tm->tm_mday = t.day; + tm->tm_mon = t.mon; + tm->tm_year = t.year; + tm->tm_wday = t.wday; + tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */ +#else + /* This routine should never be invoked. It is here just to make the + program compile. + */ +#endif +} + + + +void +set_hardware_clock_kd(const struct tm new_broken_time, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time . Use ioctls to + /dev/tty1 on what we assume is an m68k machine. + + Note that we don't use /dev/console here. That might be a serial console. +----------------------------------------------------------------------------*/ +#ifdef KDGHWCLK + int con_fd; /* File descriptor of /dev/tty1 */ + struct hwclk_time t; + + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd < 0) { + fprintf(stderr, "%s: Error opening /dev/tty1. Errno: %s (%d)\n", + MYNAME, strerror(errno), errno); + exit(1); + } else { + int rc; /* locally used return code */ + + t.sec = new_broken_time.tm_sec; + t.min = new_broken_time.tm_min; + t.hour = new_broken_time.tm_hour; + t.day = new_broken_time.tm_mday; + t.mon = new_broken_time.tm_mon; + t.year = new_broken_time.tm_year; + t.wday = new_broken_time.tm_wday; + + if (testing) + printf("Not setting Hardware Clock because running in test mode.\n"); + else { + rc = ioctl(con_fd, kdshwclk_ioctl, &t ); + if (rc < 0) { + fprintf(stderr, "%s: ioctl() to open /dev/tty1 failed. " + "Errno: %s (%d)\n", + MYNAME, strerror(errno), errno); + exit(1); + } + } + close(con_fd); + } +#else + /* This function should never be invoked. It is here just to make the + program compile. + */ +#endif +} + + + +void +see_if_kdghwclk_works(bool * const kdghwclk_works_p) { +/*---------------------------------------------------------------------------- + Find out if we are capable of accessing the Hardware Clock via the + KDHWCLK facility (ioctl to /dev/tty1). +-----------------------------------------------------------------------------*/ + if (got_kdghwclk) { + int con_fd; + struct hwclk_time t; + + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd >= 0) { + if (ioctl( con_fd, kdghwclk_ioctl, &t ) >= 0) + *kdghwclk_works_p = TRUE; + else { + if (errno == EINVAL) { + /* KDGHWCLK not implemented in this kernel... */ + *kdghwclk_works_p = FALSE; + if (debug) + printf(MYNAME "was built with KDGHWCLK capability, but the " + "ioctl does not exist in the kernel. The ioctl (to " + "/dev/tty1) failed with errno EINVAL.\n"); + } else { + *kdghwclk_works_p = FALSE; + fprintf(stderr, + "%s: KDGHWCLK ioctl failed, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + } + } + } else { + *kdghwclk_works_p = FALSE; + fprintf(stderr, + "%s: Can't open /dev/tty1. open() errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + } + close(con_fd); + } else *kdghwclk_works_p = FALSE; +} + + + diff --git a/clockB/rtc.c b/clockB/rtc.c new file mode 100644 index 00000000..46041b29 --- /dev/null +++ b/clockB/rtc.c @@ -0,0 +1,425 @@ +/************************************************************************** + + This is a component of the hwclock program. + + This file contains the code for accessing the hardware clock via + the rtc device driver (usually hooked up to the /dev/rtc device + special file). + +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "hwclock.h" + +/* + Get defines for rtc stuff. + + Getting the rtc defines is nontrivial. The obvious way is by + including but that again includes + which again includes ... and on sparc and alpha this gives + compilation errors for many kernel versions. So, we give the defines + ourselves here. Moreover, some Sparc person decided to be + incompatible, and used a struct rtc_time different from that used in + mc146818rtc.h. +*/ + +/* On Sparcs, there is a that defines different ioctls + (that are required on my machine). However, this include file + does not exist on other architectures. */ +/* One might do: +#ifdef __sparc__ +#include +#endif + */ + +/* The following is roughly equivalent */ +struct sparc_rtc_time +{ + int sec; /* Seconds (0-59) */ + int min; /* Minutes (0-59) */ + int hour; /* Hour (0-23) */ + int dow; /* Day of the week (1-7) */ + int dom; /* Day of the month (1-31) */ + int month; /* Month of year (1-12) */ + int year; /* Year (0-99) */ +}; + + +#define RTCGET _IOR('p', 20, struct sparc_rtc_time) +#define RTCSET _IOW('p', 21, struct sparc_rtc_time) + + +#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 + it conditional on i386 or something too -janl */ +#if LINUX_VERSION_CODE >= 131072 +#include +static const bool got_rtc = TRUE; +#else +static const bool got_rtc = FALSE; +#endif + +/* struct linux_rtc_time is present since Linux 1.3.99 */ +/* Earlier (since 1.3.89), a struct tm was used. */ +struct linux_rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +/* RTC_RD_TIME etc have this definition since Linux 1.99.9 (pre2.0-9) */ +#ifndef RTC_RD_TIME +#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) +#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ +#define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */ +#endif +/* RTC_EPOCH_READ and RTC_EPOCH_SET ioctls are in kernels since + Linux 2.0.34 and 2.1.89 + */ +#ifndef RTC_EPOCH_READ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ +#endif + + + +static void +do_rtc_read_ioctl(int rtc_fd, struct tm *tm, int *retcode_p) { +/*---------------------------------------------------------------------------- + Do the ioctl to read the time. This is, unfortunately, a slightly + different function for Sparc than for everything else. But we + return the standard 'tm' structure result in spite of the fact that + the Sparc ioctl returns something else. + + If the ioctl fails, issue message to stderr and return rc = 1; + else, no message and rc = 0. +-----------------------------------------------------------------------------*/ + int rc; + +#ifdef __sparc__ + struct sparc_rtc_time stm; + + rc = ioctl(rtc_fd, RTCGET, &stm); + tm->tm_sec = stm.sec; + tm->tm_min = stm.min; + tm->tm_hour = stm.hour; + tm->tm_mday = stm.dom; + tm->tm_mon = stm.month - 1; + tm->tm_year = stm.year - 1900; + tm->tm_wday = stm.dow - 1; + tm->tm_yday = -1; /* day in the year */ +#else + rc = ioctl(rtc_fd, RTC_RD_TIME, tm); +#endif + if (rc == -1) { + fprintf(stderr, "%s: ioctl() to /dev/rtc to read the time failed. " + "errno = %s (%d)\n", MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else *retcode_p = 0; + tm->tm_isdst = -1; /* don't know whether it's daylight */ + return; +} + + + +void +get_epoch(unsigned long *epoch_p, char **reason_p){ +/*---------------------------------------------------------------------------- + Get the Hardware Clock epoch setting from the kernel. + + If we succeed, return the setting (number of year A.D.) as + *epoch_p and *reason_p == NULL. + + If we fail, return and English description of what went wrong as a + null-terminated string in newly malloc'ed storage and the pointer to + it as *reason_p. +----------------------------------------------------------------------------*/ + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + if (errno == ENOENT) + *reason_p = + strdup("To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file /dev/rtc. This file does not exist on this system.\n"); + else { + *reason_p = malloc(200); + sprintf(*reason_p, "Unable to open /dev/rtc, open() errno = %s (%d)\n", + strerror(errno), errno); + } + } else { + int rc; /* return code from ioctl */ + rc = ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p); + if (rc == -1) { + *reason_p = malloc(200); + sprintf(*reason_p, "ioctl(RTC_EPOCH_READ) to /dev/rtc failed, " + "errno = %s (%d).\n", strerror(errno), errno); + } else { + *reason_p = NULL; + if (debug) printf("we have read epoch %ld from /dev/rtc " + "with RTC_EPOCH_READ ioctl.\n", *epoch_p); + } + close(rtc_fd); + } + return; +} + + + +static void +busywait_for_rtc_clock_tick(const int rtc_fd, int *retcode_p) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by reading /dev/rtc in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + struct tm start_time; + /* The time when we were called (and started waiting) */ + int rc; + + if (debug) + printf("Waiting in loop for time from /dev/rtc to change\n"); + + do_rtc_read_ioctl(rtc_fd, &start_time, &rc); + if (rc != 0) *retcode_p = 1; + else { + /* Wait for change. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + struct tm nowtime; + int iterations; /* how many time's we've spun through the loop */ + int rc; /* Return code from do_rtc_read_ioctl */ + + iterations = 0; + do { + do_rtc_read_ioctl(rtc_fd, &nowtime, &rc); + } while (rc == 0 && start_time.tm_sec == nowtime.tm_sec + && iterations++ < 1000000); + + if (iterations >= 1000000) { + fprintf(stderr, "%s: Timed out waiting for time change.\n", MYNAME); + *retcode_p = 2; + } else if (rc != 0) *retcode_p = 3; + else *retcode_p = 0; + } +} + + + +void +synchronize_to_clock_tick_RTC(int *retcode_p) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for /dev/rtc. +-----------------------------------------------------------------------------*/ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open("/dev/rtc", O_RDONLY); + + if (rtc_fd == -1) { + fprintf(stderr, "%s: open() of /dev/rtc failed, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else { + int rc; /* Return code from ioctl */ + /* Turn on update interrupts (one per second) */ + rc = ioctl(rtc_fd, RTC_UIE_ON, 0); + if (rc == -1 && errno == EINVAL) { + /* This rtc device doesn't have interrupt functions. This is typical + on an Alpha, where the Hardware Clock interrupts are used by the + kernel for the system clock, so aren't at the user's disposal. + */ + if (debug) printf("/dev/rtc does not have interrupt functions. \n"); + busywait_for_rtc_clock_tick(rtc_fd, retcode_p); + } else if (rc != -1) { + int rc; /* return code from ioctl */ + unsigned long dummy; + + /* this blocks until the next update interrupt */ + rc = read(rtc_fd, &dummy, sizeof(dummy)); + if (rc == -1) { + fprintf(stderr, "%s: read() to /dev/rtc to wait for clock tick " + "failed, errno = %s (%d).\n", MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else { + *retcode_p = 0; + } + /* Turn off update interrupts */ + rc = ioctl(rtc_fd, RTC_UIE_OFF, 0); + if (rc == -1) { + fprintf(stderr, + "%s: ioctl() to /dev/rtc to turn off update interrupts " + "failed, errno = %s (%d).\n", MYNAME, strerror(errno), errno); + } + } else { + fprintf(stderr, "%s: ioctl() to /dev/rtc to turn on update interrupts " + "failed unexpectedly, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); + *retcode_p = 1; + } + close(rtc_fd); + } +} + + + +void +read_hardware_clock_rtc_ioctl(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to "rtc" device /dev/rtc. +-----------------------------------------------------------------------------*/ + int rc; /* Local return code */ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open("/dev/rtc",O_RDONLY); +if (rtc_fd == -1) { +fprintf(stderr, "%s: open() of /dev/rtc failed, errno = %s (%d).\n", + MYNAME, strerror(errno), errno); +exit(5); + } else { + /* Read the RTC time/date */ + + rc = ioctl(rtc_fd, RTC_RD_TIME, tm); + if (rc == -1) { + fprintf(stderr, "%s: ioctl() to /dev/rtc to read the time failed, " + "errno = %s (%d).\n", MYNAME, strerror(errno), errno); + exit(5); + } + close(rtc_fd); + } + tm->tm_isdst = -1; /* don't know whether it's daylight */ +} + + + +void +set_hardware_clock_rtc_ioctl(const struct tm new_broken_time, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the broken down time . + Use ioctls to "rtc" device /dev/rtc. +----------------------------------------------------------------------------*/ + int rc; + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + fprintf(stderr, "%s: Unable to open /dev/rtc, open() errno = %s (%d)\n", + MYNAME, strerror(errno), errno); + exit(5); + } else { + if (testing) + printf("Not setting Hardware Clock because running in test mode.\n"); + else { + rc = ioctl(rtc_fd, RTC_SET_TIME, &new_broken_time); + if (rc == -1) { + fprintf(stderr, + "%s: ioctl() (RTC_SET_TIME) to /dev/rtc to set time failed, " + "errno = %s (%d).\n", MYNAME, strerror(errno), errno); + exit(5); + } else { + if (debug) + printf("ioctl(RTC_SET_TIME) was successful.\n"); + } + } + close(rtc_fd); + } +} + + + +void +set_epoch(unsigned long epoch, const bool testing, int *retcode_p) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock epoch in the kernel. +----------------------------------------------------------------------------*/ + if (epoch < 1900) + /* kernel would not accept this epoch value */ + fprintf(stderr, "%s: The epoch value may not be less than 1900. " + "You requested %ld\n", MYNAME, epoch); + else { + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + if (errno == ENOENT) + fprintf(stderr, + "%s: To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file /dev/rtc. This file does not exist on this system.\n", + MYNAME); + fprintf(stderr, "%s: Unable to open /dev/rtc, open() errno = %s (%d)\n", + MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else { + if (debug) printf("setting epoch to %ld " + "with RTC_EPOCH_SET ioctl to /dev/rtc.\n", epoch); + if (testing) { + printf("Not setting epoch because running in test mode.\n"); + *retcode_p = 0; + } else { + int rc; /* return code from ioctl */ + rc = ioctl(rtc_fd, RTC_EPOCH_SET, epoch); + if (rc == -1) { + if (errno == EINVAL) + fprintf(stderr, "%s: The kernel (specifically, the device driver " + "for /dev/rtc) does not have the RTC_EPOCH_SET ioctl. " + "Get a newer driver.\n", MYNAME); + else + fprintf(stderr, "%s: ioctl(RTC_EPOCH_SET) to /dev/rtc failed, " + "errno = %s (%d).\n", MYNAME, strerror(errno), errno); + *retcode_p = 1; + } else *retcode_p = 0; + } + close(rtc_fd); + } + } +} + + + +void +see_if_rtc_works(bool * const rtc_works_p) { +/*---------------------------------------------------------------------------- + Find out if we are capable of accessing the Hardware Clock via the rtc + driver (via device file /dev/rtc). +-----------------------------------------------------------------------------*/ + if (got_rtc) { + int rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd > 0) { + *rtc_works_p = TRUE; + close(rtc_fd); + } else { + *rtc_works_p = FALSE; + if (debug) + printf("Open of /dev/rtc failed, errno = %s (%d). " + "falling back to more primitive clock access method.\n", + strerror(errno), errno); + } + } else { + if (debug) + printf("The Linux kernel for which this copy of hwclock() was built " + "is too old to have /dev/rtc\n"); + *rtc_works_p = FALSE; + } +} + + + + diff --git a/sys-utils/shhopt.c b/clockB/shhopt.c similarity index 100% rename from sys-utils/shhopt.c rename to clockB/shhopt.c diff --git a/clockB/shhopt.h b/clockB/shhopt.h new file mode 100644 index 00000000..3f87c138 --- /dev/null +++ b/clockB/shhopt.h @@ -0,0 +1,33 @@ +/* $Id: shhopt.h,v 1.2 1996/06/06 00:06:35 sverrehu Exp $ */ +#ifndef SHHOPT_H +#define SHHOPT_H + +/* constants for recognized option types. */ +typedef enum { + OPT_END, /* nothing. used as ending element. */ + OPT_FLAG, /* no argument following. sets variable to 1. */ + OPT_STRING, /* string argument. */ + OPT_INT, /* signed integer argument. */ + OPT_UINT, /* unsigned integer argument. */ + OPT_LONG, /* signed long integer argument. */ + OPT_ULONG, /* unsigned long integer argument. */ +} optArgType; + +/* flags modifying the default way options are handeled. */ +#define OPT_CALLFUNC 1 /* pass argument to a function. */ + +typedef struct { + char shortName; /* Short option name. */ + char *longName; /* Long option name, no including '--'. */ + optArgType type; /* Option type. */ + void *arg; /* Pointer to variable to fill with argument, + * or pointer to function if Type == OPT_FUNC. */ + int flags; /* Modifier flags. */ +} optStruct; + + +void optSetFatalFunc(void (*f)(const char *, ...)); +void optParseOptions(int *argc, char *argv[], + const optStruct opt[], const int allowNegNum); + +#endif diff --git a/clockB/util.c b/clockB/util.c new file mode 100644 index 00000000..8a1a6060 --- /dev/null +++ b/clockB/util.c @@ -0,0 +1,120 @@ +/************************************************************************** + + This is a component of the hwclock program. + + This file contains the code for various basic utility routines + needed by the other modules. + +****************************************************************************/ + +#include +#include + +#include "hwclock.h" + +bool +is_in_cpuinfo(const char * const fmt, const char * const str) { +/*---------------------------------------------------------------------------- + Return true iff the /proc/cpuinfo file shows the value 'str' for the + keyword 'fmt'. Both arguments are null-terminated strings. + + If for any reason we can't read /proc/cpuinfo, return false. +-----------------------------------------------------------------------------*/ + FILE *cpuinfo; + char field[256]; + char format[256]; + bool found; + + sprintf(format, "%s : %s", fmt, "%255s"); + + found = FALSE; /* initial value */ + if ((cpuinfo = fopen ("/proc/cpuinfo", "r")) != NULL) { + while (!feof(cpuinfo)) { + if (fscanf (cpuinfo, format, field) == 1) { + if (strncmp(field, str, strlen(str)) == 0) + found = TRUE; + break; + } + fgets (field, 256, cpuinfo); + } + fclose(cpuinfo); + } + return found; +} + + + +char * +ctime2(const time_t time) { +/*---------------------------------------------------------------------------- + Same as ctime() from the standard C library, except it takes a time_t + as an argument instead of a pointer to a time_t, so it is much more + useful. + + Also, don't include a newline at the end of the returned string. If + the user wants a newline, he can provide it himself. + + return value is in static storage within. +-----------------------------------------------------------------------------*/ + static char retval[30]; + + strncpy(retval, ctime(&time), sizeof(retval)); + retval[sizeof(retval)-1] = '\0'; + + /* Now chop off the last character, which is the newline */ + if (strlen(retval) >= 1) /* for robustness */ + retval[strlen(retval)-1] = '\0'; + return(retval); + +} + + + +struct timeval +t2tv(time_t argument) { +/*---------------------------------------------------------------------------- + Convert from "time_t" format to "timeval" format. +-----------------------------------------------------------------------------*/ + struct timeval retval; + + retval.tv_sec = argument; + retval.tv_usec = 0; + return(retval); +} + + + +float +time_diff(struct timeval subtrahend, struct timeval subtractor) { +/*--------------------------------------------------------------------------- + The difference in seconds between two times in "timeval" format. +----------------------------------------------------------------------------*/ + return( (subtrahend.tv_sec - subtractor.tv_sec) + + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 ); +} + + +struct timeval +time_inc(struct timeval addend, float increment) { +/*---------------------------------------------------------------------------- + The time, in "timeval" format, which is seconds after + the time . Of course, may be negative. +-----------------------------------------------------------------------------*/ + struct timeval newtime; + + newtime.tv_sec = addend.tv_sec + (int) increment; + newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6; + + /* Now adjust it so that the microsecond value is between 0 and 1 million */ + if (newtime.tv_usec < 0) { + newtime.tv_usec += 1E6; + newtime.tv_sec -= 1; + } else if (newtime.tv_usec >= 1E6) { + newtime.tv_usec -= 1E6; + newtime.tv_sec += 1; + } + return(newtime); +} + + + diff --git a/configure b/configure new file mode 100755 index 00000000..75f75464 --- /dev/null +++ b/configure @@ -0,0 +1,362 @@ +#!/bin/sh +# Configure script for util-linux - aeb, 990205 +# +# We need to find out the following things: +# +# 1. For mount/nfsmount.c: is inet_aton() available? +# 2. For fdisk/fdisksunlabel.c: is there a ? +# For fdisk/fdisk.c: is there a ? +# 3. For sys-utils/ipcs.c: do we need __KERNEL__ and ? +# 4. For sys-utils/cytune.c: do we need ? +# 5. For sys-utils/kbd_rate.c: does exist? +# 6. For cfdisk, setterm, more, ul: do we have ncurses? How installed? +# For more: do we have libtermcap? +# 7. For chfn, chsh, login, newgrp, passwd: do we need -lcrypt? +# 8. For sln: does static compilation work? +# 9. For lib/nls.h: do we have ? +# 10. For lib/nls.h: do we have and gettext()? +# 11. For xgettext: does it take the option --foreign-user? +# 12. For cal.c: do we have ? +# 13. For err.c: do we have __progname? +# 14. For script.c: do we have and openpty()? + +if test "$RANDOM" = "$RANDOM"; then + # Plain old Bourne shell. + echo checking for gcc + test -z "$CC" -a -n "`gcc 2>&1`" && CC="gcc -O" +else + # ksh, bash or zsh. ksh and zsh write "command not found" to stderr. + echo checking for gcc + test -z "$CC" && type gcc && CC="gcc -O" +fi + +CC=${CC-cc} +CFLAGS=${CFLAGS-"-O"} +DEFS= +LIBS= +compile='$CC $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' +static_compile='$CC -static $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' + +rm -f make_include defines.h conftest.c conftest + +# +# 1. For mount/nfsmount.c: is inet_aton() available? +# +echo " +#include +#include +#include +main(int a, char **v){ + if (a == -1) /* false */ + inet_aton((const char *) 0, (struct in_addr *) 0); + exit(0); +} +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_inet_aton" >> defines.h + echo "You have inet_aton()" +else + echo "You don't have inet_aton()" +fi +rm -f conftest conftest.c + +# +# 2. For fdisk/fdisksunlabel.c: is available? +# Some kernels have that uses u_char +# But maybe there is already a typedef. Let us use a #define +# +echo " +#define u_char unsigned char +#include +#undef u_char +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_scsi_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + +# +# 2A. For fdisk/fdisk.c: is available? +# +echo " +#include +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_blkpg_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + +# +# 3. ipcs.c includes and family +# Do we need __KERNEL__ and asmlinkage for SHM_DEST? +# +echo " +#include +main(){ int i=SHM_DEST; exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "You don't need " +else + echo "#define NEED_linkage_h" >> defines.h + echo "You need " +fi +rm -f conftest conftest.c + +# +# 4. cytune.c may need struct tq_struct +# +echo " +#include +#include +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "You don't need " +else + echo "#define NEED_tqueue_h" >> defines.h + echo "You need " +fi +rm -f conftest conftest.c + +# +# 5. Does exist? +# +echo " +#include +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_kd_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + +# +# 6. How is [n]curses installed? +# +test_curses_h=0 +have_ncurses=1 +if [ -f /usr/include/ncurses/curses.h ]; then + echo "HAVE_NCURSES=yes" >> make_include + echo "CURSESFLAGS=-I/usr/include/ncurses -DNCH=0" >> make_include + echo "You have ncurses. Using ." +elif [ -f /usr/include/ncurses.h ]; then + echo "HAVE_NCURSES=yes" >> make_include + echo "CURSESFLAGS=-DNCH=1" >> make_include + echo "You have ncurses. Using ." +elif [ -f /usr/local/include/ncurses.h ]; then + echo "HAVE_NCURSES=yes" >> make_include + echo "CURSESFLAGS=-I/usr/local/include -DNCH=1" >> make_include + echo "You have ncurses. Using /usr/local/include/ncurses.h." +elif [ -f /usr/include/curses.h ]; then + test_curses_h=1 +else + have_ncurses=0 +fi +# +# If we found a curses.h, test whether it is ncurses +# (It should define __NCURSES_H and NCURSES_VERSION and NCURSES_CONST ...) +# +if [ $test_curses_h = 1 ]; then + echo " + #include + main(){ char *c = NCURSES_VERSION; exit(0); } + " > conftest.c + eval $compile + if test -s conftest && ./conftest 2>/dev/null; then + echo "HAVE_NCURSES=yes" >> make_include + echo "CURSESFLAGS=-DNCH=0" >> make_include + echo "You have ncurses. Using ." + else + have_ncurses=0 + fi + rm -f conftest conftest.c +fi + +if [ $have_ncurses = 0 ]; then + echo "HAVE_NCURSES=no" >> make_include + echo "You don't have ncurses - I will not make ul and setterm." +else + echo "LIBCURSES=-lncurses" >> make_include +fi + +# +# Some systems have /usr/lib/termcap.so -> /usr/lib/termcap.so.2 +# where however the latter file does not exist. When termcap does +# not exist, we can try to compile more with curses instead. +# +echo ' +#include +main(){ exit(0); tgetnum("li"); } +' > conftest.c +LIBS=-ltermcap +eval $compile +LIBS= +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_termcap" >> defines.h + echo "LIBTERMCAP=-ltermcap" >> make_include + echo "You have termcap" +else + echo "HAVE_TERMCAP=no" >> make_include + echo "You don't have termcap" +fi +rm -f conftest conftest.c + +# +# 7. Do we need -lcrypt? +# +echo ' +#define _XOPEN_SOURCE +#include +main(){ char *c = crypt("abc","pw"); exit(0); } +' > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "NEED_LIBCRYPT=no" >> make_include + echo "You don't need -lcrypt" +else + echo "NEED_LIBCRYPT=yes" >> make_include + echo "You need -lcrypt" +fi +rm -f conftest conftest.c + +# +# 8. Does static compilation work? +# +echo " +main(){ return 0; } +" > conftest.c +eval $static_compile +if test -s conftest && ./conftest 2>/dev/null; then + : OK, nothing special +else + echo "CAN_DO_STATIC=no" >> make_include + echo "Strange... Static compilation fails here." +fi + +# +# 9. For lib/nls.h: do we have ? +# +echo " +#include +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_locale_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + + +# +# 10. For lib/nls.h: do we have and gettext() ? +# +echo ' +#include +main(int a, char **v){ + if (a == -1) /* false */ + gettext("There is no gettext man page\n"); + exit(0); +} +' > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo '#define HAVE_libintl_h' >> defines.h + echo "You have and gettext()" + echo '#define ENABLE_NLS' >> defines.h + echo "Assuming that you want to enable NLS support." + echo "(Otherwise, edit defines.h)" + ENABLE_NLS=yes +else + echo "You don't have " + ENABLE_NLS=no +fi +rm -f conftest conftest.c + + +# +# 11. Does xgettext exist and take the option --foreign-user? +# +if (test $ENABLE_NLS = yes && type xgettext > /dev/null 2>&1); then + msg=`xgettext --foreign-user 2>&1 | grep unrecognized` + if test -n "$msg"; then + echo "FOREIGN = " >> make_include + else + echo "FOREIGN = --foreign-user" >> make_include + fi + echo "HAVE_XGETTEXT=yes" >> make_include +else + echo "HAVE_XGETTEXT=no" >> make_include +fi + +# +# 12. For cal.c: do we have ? +# +echo " +#include +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_langinfo_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + + +# +# 13. For err.c: do we have __progname? +# [make sure gcc -O does not optimize the access away] +# +echo " +#include +extern char *__progname; +main(){ printf(__progname); exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest > /dev/null 2>/dev/null; then + echo "#define HAVE_progname" >> defines.h + echo "You have __progname" +else + echo "You don't have __progname" +fi +rm -f conftest conftest.c + + +# +# 14. For script.c: do we have and openpty()? +# +echo " +#include +main(){ exit(0); openpty(0, 0, 0, 0, 0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "HAVE_OPENPTY=yes" >> make_include + echo "#define HAVE_openpty" >> defines.h + echo "You have and openpty()" +else + echo "You don't have and openpty()" +fi +rm -f conftest conftest.c diff --git a/disk-utils/Makefile b/disk-utils/Makefile index aec38630..b170e81e 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -4,6 +4,7 @@ # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) # +include ../make_include include ../MCONFIG # Where to put man pages? diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c index 7f792c5c..bb4f0a1f 100644 --- a/disk-utils/fdformat.c +++ b/disk-utils/fdformat.c @@ -1,5 +1,11 @@ /* fdformat.c - Low-level formats a floppy disk. */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * 1999-03-20 Arnaldo Carvalho de Melo + & - more i18n/nls translatable strings marked + */ + #include #include #include @@ -10,6 +16,7 @@ #include #include #include +#include "nls.h" static int ctrl; struct floppy_struct param; @@ -23,7 +30,7 @@ static void format_disk(char *name) struct format_descr descr; int track; - printf("Formatting ... "); + printf(_("Formatting ... ")); fflush(stdout); if (ioctl(ctrl,FDFMTBEG,NULL) < 0) PERROR("\nioctl(FDFMTBEG)"); for (track = 0; track < param.track; track++) { @@ -41,7 +48,7 @@ static void format_disk(char *name) } } if (ioctl(ctrl,FDFMTEND,NULL) < 0) PERROR("\nioctl(FDFMTEND)"); - printf("done\n"); + printf(_("done\n")); } @@ -52,7 +59,7 @@ static void verify_disk(char *name) cyl_size = param.sect*param.head*512; if ((data = (unsigned char *) malloc(cyl_size)) == NULL) PERROR("malloc"); - printf("Verifying ... "); + printf(_("Verifying ... ")); fflush(stdout); if ((fd = open(name,O_RDONLY)) < 0) PERROR(name); for (cyl = 0; cyl < param.track; cyl++) { @@ -63,20 +70,20 @@ static void verify_disk(char *name) read_bytes = read(fd,data,cyl_size); if(read_bytes != cyl_size) { if(read_bytes < 0) - perror("Read: "); + perror(_("Read: ")); fprintf(stderr, - "Problem reading cylinder %d, expected %d, read %d\n", + _("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); + printf(_("bad data in cyl %d\nContinuing ... "),cyl); fflush(stdout); break; } } - printf("done\n"); + printf(_("done\n")); if (close(fd) < 0) PERROR("close"); } @@ -86,7 +93,7 @@ static void usage(char *name) char *this; if ((this = strrchr(name,'/')) != NULL) name = this+1; - fprintf(stderr,"usage: %s [ -n ] device\n",name); + fprintf(stderr,_("usage: %s [ -n ] device\n"),name); exit(1); } @@ -97,6 +104,10 @@ int main(int argc,char **argv) char *name; struct stat st; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + name = argv[0]; verify = 1; if (argc > 1 && argv[1][0] == '-') { @@ -108,15 +119,15 @@ int main(int argc,char **argv) if (argc != 2) usage(name); if (stat(argv[1],&st) < 0) PERROR(argv[1]); if (!S_ISBLK(st.st_mode) || MAJOR(st.st_rdev) != FLOPPY_MAJOR) { - fprintf(stderr,"%s: not a floppy device\n",argv[1]); + fprintf(stderr,_("%s: not a floppy device\n"),argv[1]); exit(1); } if (access(argv[1],W_OK) < 0) PERROR(argv[1]); if ((ctrl = open(argv[1],3)) < 0) PERROR(argv[1]); if (ioctl(ctrl,FDGETPRM,(long) ¶m) < 0) - PERROR("Could not determine current format type"); - printf("%sle-sided, %d tracks, %d sec/track. Total capacity %d kB.\n", - param.head ? "Doub" : "Sing",param.track,param.sect,param.size >> 1); + PERROR(_("Could not determine current format type")); + printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"), + param.head ? _("Double") : _("Single"),param.track,param.sect,param.size >> 1); format_disk(argv[1]); if (verify) verify_disk(argv[1]); return 0; diff --git a/disk-utils/fsck.minix.c b/disk-utils/fsck.minix.c index ba64bf34..416c178c 100644 --- a/disk-utils/fsck.minix.c +++ b/disk-utils/fsck.minix.c @@ -62,6 +62,10 @@ * 06.11.96 - Added v2 code submitted by Joerg Dorchain, but written by * Andreas Schwab. * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * + * * I've had no time to add comments - hopefully the function names * are comments enough. As with all file system checkers, this assumes * the file system is quiescent - don't use it on a mounted device @@ -95,6 +99,7 @@ #include #include #include "../version.h" +#include "nls.h" #ifdef MINIX2_SUPER_MAGIC2 #define HAVE_MINIX2 1 @@ -189,8 +194,8 @@ void fatal_error(const char * fmt_string, int status) exit(status); } -#define usage() fatal_error("Usage: %s [-larvsmf] /dev/name\n",16) -#define die(str) fatal_error("%s: " str "\n",8) +#define usage() fatal_error(_("Usage: %s [-larvsmf] /dev/name\n"),16) +#define die(str) fatal_error(_("%s: " str "\n"),8) /* * This simply goes through the file-name data and prints out the @@ -206,7 +211,7 @@ void print_current_name(void) printf ("/"); } -int ask(const char * string,int def) +int ask(const char * string, int def) { int c; @@ -280,13 +285,13 @@ static void check_mount(void) else close(fd); - printf ("%s is mounted. ", device_name); + printf (_("%s is mounted. "), device_name); if (isatty(0) && isatty(1)) - cont = ask("Do you really want to continue", 0); + cont = ask(_("Do you really want to continue"), 0); else cont = 0; if (!cont) { - printf ("check aborted.\n"); + printf (_("check aborted.\n")); exit (0); } return; @@ -303,14 +308,14 @@ int check_zone_nr(unsigned short * nr, int * corrected) if (!*nr) return 0; if (*nr < FIRSTZONE) - printf("Zone nr < FIRSTZONE in file `"); + printf(_("Zone nr < FIRSTZONE in file `")); else if (*nr >= ZONES) - printf("Zone nr >= ZONES in file `"); + printf(_("Zone nr >= ZONES in file `")); else return *nr; print_current_name(); printf("'."); - if (ask("Remove block",1)) { + if (ask(_("Remove block"),1)) { *nr = 0; *corrected = 1; } @@ -323,14 +328,14 @@ int check_zone_nr2 (unsigned int *nr, int *corrected) if (!*nr) return 0; if (*nr < FIRSTZONE) - printf ("Zone nr < FIRSTZONE in file `"); + printf (_("Zone nr < FIRSTZONE in file `")); else if (*nr >= ZONES) - printf ("Zone nr >= ZONES in file `"); + printf (_("Zone nr >= ZONES in file `")); else return *nr; print_current_name (); printf ("'."); - if (ask ("Remove block", 1)) { + if (ask (_("Remove block"), 1)) { *nr = 0; *corrected = 1; } @@ -348,13 +353,13 @@ void read_block(unsigned int nr, char * addr) return; } if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) { - printf("Read error: unable to seek to block in file '"); + printf(_("Read error: unable to seek to block in file '")); print_current_name(); printf("'\n"); memset(addr,0,BLOCK_SIZE); errors_uncorrected = 1; } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { - printf("Read error: bad block in file '"); + printf(_("Read error: bad block in file '")); print_current_name(); printf("'\n"); memset(addr,0,BLOCK_SIZE); @@ -370,15 +375,15 @@ void write_block(unsigned int nr, char * addr) if (!nr) return; if (nr < FIRSTZONE || nr >= ZONES) { - printf("Internal error: trying to write bad block\n" - "Write request ignored\n"); + printf(_("Internal error: trying to write bad block\n" + "Write request ignored\n")); errors_uncorrected = 1; return; } if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET)) die("seek failed in write_block"); if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { - printf("Write error: bad block in file '"); + printf(_("Write error: bad block in file '")); print_current_name(); printf("'\n"); errors_uncorrected = 1; @@ -599,18 +604,18 @@ void read_tables(void) if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE)) die("Unable to read inodes"); if (NORM_FIRSTZONE != FIRSTZONE) { - printf("Warning: Firstzone != Norm_firstzone\n"); + printf(_("Warning: Firstzone != Norm_firstzone\n")); errors_uncorrected = 1; } get_dirsize (); if (show) { - printf("%ld inodes\n",INODES); - printf("%ld blocks\n",ZONES); - printf("Firstdatazone=%ld (%ld)\n",FIRSTZONE,NORM_FIRSTZONE); - printf("Zonesize=%d\n",BLOCK_SIZE<i_mode); + printf(_(" has mode %05o\n"),inode->i_mode); } } else links++; if (!++inode_count[nr]) { - printf("Warning: inode count too big.\n"); + printf(_("Warning: inode count too big.\n")); inode_count[nr]--; errors_uncorrected = 1; } @@ -676,11 +681,11 @@ get_inode2 (unsigned int nr) inode = Inode2 + nr; if (!inode_count[nr]) { if (!inode_in_use (nr)) { - printf ("Inode %d marked not used, but used for file '", nr); + printf (_("Inode %d marked not used, but used for file '"), nr); print_current_name (); printf ("'\n"); if (repair) { - if (ask ("Mark in use", 1)) + if (ask (_("Mark in use"), 1)) mark_inode (nr); else errors_uncorrected = 1; @@ -700,12 +705,12 @@ get_inode2 (unsigned int nr) else if (S_ISFIFO (inode->i_mode)); else { print_current_name (); - printf (" has mode %05o\n", inode->i_mode); + printf (_(" has mode %05o\n"), inode->i_mode); } } else links++; if (!++inode_count[nr]) { - printf ("Warning: inode count too big.\n"); + printf (_("Warning: inode count too big.\n")); inode_count[nr]--; errors_uncorrected = 1; } @@ -741,10 +746,10 @@ static int add_zone(unsigned short * znr, int * corrected) if (!block) return 0; if (zone_count[block]) { - printf("Block has been used before. Now in file `"); + printf(_("Block has been used before. Now in file `")); print_current_name(); printf("'."); - if (ask("Clear",1)) { + if (ask(_("Clear"),1)) { *znr = 0; block = 0; *corrected = 1; @@ -753,10 +758,10 @@ static int add_zone(unsigned short * znr, int * corrected) if (!block) return 0; if (!zone_in_use(block)) { - printf("Block %d in file `",block); + printf(_("Block %d in file `"),block); print_current_name(); - printf("' is marked not in use."); - if (ask("Correct",1)) + printf(_("' is marked not in use.")); + if (ask(_("Correct"),1)) mark_zone(block); } if (!++zone_count[block]) @@ -775,10 +780,10 @@ static int add_zone2 (unsigned int *znr, int *corrected) if (!block) return 0; if (zone_count[block]) { - printf ("Block has been used before. Now in file `"); + printf (_("Block has been used before. Now in file `")); print_current_name (); printf ("'."); - if (ask ("Clear", 1)) { + if (ask (_("Clear"), 1)) { *znr = 0; block = 0; *corrected = 1; @@ -787,10 +792,10 @@ static int add_zone2 (unsigned int *znr, int *corrected) if (!block) return 0; if (!zone_in_use (block)) { - printf ("Block %d in file `", block); + printf (_("Block %d in file `"), block); print_current_name (); - printf ("' is marked not in use."); - if (ask ("Correct", 1)) + printf (_("' is marked not in use.")); + if (ask (_("Correct"), 1)) mark_zone (block); } if (!++zone_count[block]) @@ -940,9 +945,9 @@ void check_file(struct minix_inode * dir, unsigned int offset) ino = * (unsigned short *) (name-2); if (ino > INODES) { print_current_name(); - printf(" contains a bad inode number for file '"); + printf(_(" contains a bad inode number for file '")); printf("%.*s'.",namelen,name); - if (ask(" Remove",1)) { + if (ask(_(" Remove"),1)) { *(unsigned short *)(name-2) = 0; write_block(block, blk); } @@ -956,14 +961,14 @@ void check_file(struct minix_inode * dir, unsigned int offset) if (!offset) { if (!inode || strcmp(".",name)) { print_current_name(); - printf(": bad directory: '.' isn't first\n"); + printf(_(": bad directory: '.' isn't first\n")); errors_uncorrected = 1; } else return; } if (offset == dirsize) { if (!inode || strcmp("..",name)) { print_current_name(); - printf(": bad directory: '..' isn't second\n"); + printf(_(": bad directory: '..' isn't second\n")); errors_uncorrected = 1; } else return; } @@ -1004,9 +1009,9 @@ check_file2 (struct minix2_inode *dir, unsigned int offset) ino = *(unsigned short *) (name - 2); if (ino > INODES) { print_current_name (); - printf (" contains a bad inode number for file '"); + printf (_(" contains a bad inode number for file '")); printf ("%.*s'.", namelen, name); - if (ask (" Remove", 1)) { + if (ask (_(" Remove"), 1)) { *(unsigned short *) (name - 2) = 0; write_block (block, blk); } @@ -1020,7 +1025,7 @@ check_file2 (struct minix2_inode *dir, unsigned int offset) if (!offset) { if (!inode || strcmp (".", name)) { print_current_name (); - printf (": bad directory: '.' isn't first\n"); + printf (_(": bad directory: '.' isn't first\n")); errors_uncorrected = 1; } else return; @@ -1028,7 +1033,7 @@ check_file2 (struct minix2_inode *dir, unsigned int offset) if (offset == dirsize) { if (!inode || strcmp ("..", name)) { print_current_name (); - printf (": bad directory: '..' isn't second\n"); + printf (_(": bad directory: '..' isn't second\n")); errors_uncorrected = 1; } else return; @@ -1063,7 +1068,7 @@ void recursive_check(unsigned int ino) die("internal error"); if (dir->i_size < 2 * dirsize) { print_current_name(); - printf(": bad directory: size<32"); + printf(_(": bad directory: size<32")); errors_uncorrected = 1; } for (offset = 0 ; offset < dir->i_size ; offset += dirsize) @@ -1082,7 +1087,7 @@ recursive_check2 (unsigned int ino) die ("internal error"); if (dir->i_size < 2 * dirsize) { print_current_name (); - printf (": bad directory: size < 32"); + printf (_(": bad directory: size < 32")); errors_uncorrected = 1; } for (offset = 0; offset < dir->i_size; offset += dirsize) @@ -1105,8 +1110,8 @@ void check_counts(void) for (i=1 ; i <= INODES ; i++) { if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) { - printf("Inode %d mode not cleared.",i); - if (ask("Clear",1)) { + printf(_("Inode %d mode not cleared."),i); + if (ask(_("Clear"),1)) { Inode[i].i_mode = 0; changed = 1; } @@ -1114,21 +1119,21 @@ void check_counts(void) if (!inode_count[i]) { if (!inode_in_use(i)) continue; - printf("Inode %d not used, marked used in the bitmap.",i); - if (ask("Clear",1)) + printf(_("Inode %d not used, marked used in the bitmap."),i); + if (ask(_("Clear"),1)) unmark_inode(i); continue; } if (!inode_in_use(i)) { - printf("Inode %d used, marked unused in the bitmap.", + printf(_("Inode %d used, marked unused in the bitmap."), i); if (ask("Set",1)) mark_inode(i); } if (Inode[i].i_nlinks != inode_count[i]) { - printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", + printf(_("Inode %d (mode = %07o), i_nlinks=%d, counted=%d."), i,Inode[i].i_mode,Inode[i].i_nlinks,inode_count[i]); - if (ask("Set i_nlinks to count",1)) { + if (ask(_("Set i_nlinks to count"),1)) { Inode[i].i_nlinks=inode_count[i]; changed=1; } @@ -1140,13 +1145,13 @@ void check_counts(void) if (!zone_count[i]) { if (bad_zone(i)) continue; - printf("Zone %d: marked in use, no file uses it.",i); - if (ask("Unmark",1)) + printf(_("Zone %d: marked in use, no file uses it."),i); + if (ask(_("Unmark"),1)) unmark_zone(i); continue; } - printf("Zone %d: %sin use, counted=%d\n", - i,zone_in_use(i)?"":"not ",zone_count[i]); + printf(_("Zone %d: %sin use, counted=%d\n"), + i,zone_in_use(i)?"":_("not "),zone_count[i]); } } @@ -1158,8 +1163,8 @@ check_counts2 (void) for (i = 1; i <= INODES; i++) { if (!inode_in_use (i) && Inode2[i].i_mode && warn_mode) { - printf ("Inode %d mode not cleared.", i); - if (ask ("Clear", 1)) { + printf (_("Inode %d mode not cleared."), i); + if (ask (_("Clear"), 1)) { Inode2[i].i_mode = 0; changed = 1; } @@ -1167,20 +1172,20 @@ check_counts2 (void) if (!inode_count[i]) { if (!inode_in_use (i)) continue; - printf ("Inode %d not used, marked used in the bitmap.", i); - if (ask ("Clear", 1)) + printf (_("Inode %d not used, marked used in the bitmap."), i); + if (ask (_("Clear"), 1)) unmark_inode (i); continue; } if (!inode_in_use (i)) { - printf ("Inode %d used, marked unused in the bitmap.", i); - if (ask ("Set", 1)) + printf (_("Inode %d used, marked unused in the bitmap."), i); + if (ask (_("Set"), 1)) mark_inode (i); } if (Inode2[i].i_nlinks != inode_count[i]) { - printf ("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", + printf (_("Inode %d (mode = %07o), i_nlinks=%d, counted=%d."), i, Inode2[i].i_mode, Inode2[i].i_nlinks, inode_count[i]); - if (ask ("Set i_nlinks to count", 1)) { + if (ask (_("Set i_nlinks to count"), 1)) { Inode2[i].i_nlinks = inode_count[i]; changed = 1; } @@ -1192,13 +1197,13 @@ check_counts2 (void) if (!zone_count[i]) { if (bad_zone (i)) continue; - printf ("Zone %d: marked in use, no file uses it.", i); - if (ask ("Unmark", 1)) + printf (_("Zone %d: marked in use, no file uses it."), i); + if (ask (_("Unmark"), 1)) unmark_zone (i); continue; } - printf ("Zone %d: %sin use, counted=%d\n", - i, zone_in_use (i) ? "" : "not ", zone_count[i]); + printf (_("Zone %d: %sin use, counted=%d\n"), + i, zone_in_use (i) ? "" : _("not "), zone_count[i]); } } #endif @@ -1230,6 +1235,11 @@ int main(int argc, char ** argv) int count; int retcode = 0; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc && *argv) program_name = *argv; if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) @@ -1283,13 +1293,13 @@ int main(int argc, char ** argv) (Super.s_state & MINIX_VALID_FS) && !force ) { if (repair) - printf("%s is clean, no check.\n", device_name); + printf(_("%s is clean, no check.\n"), device_name); return retcode; } else if (force) - printf("Forcing filesystem check on %s.\n", device_name); + printf(_("Forcing filesystem check on %s.\n"), device_name); else if (repair) - printf("Filesystem on %s is dirty, needs checking.\n",\ + printf(_("Filesystem on %s is dirty, needs checking.\n"),\ device_name); read_tables(); @@ -1318,29 +1328,29 @@ int main(int argc, char ** argv) for (i=1,free=0 ; i <= INODES ; i++) if (!inode_in_use(i)) free++; - printf("\n%6ld inodes used (%ld%%)\n",(INODES-free), + printf(_("\n%6ld inodes used (%ld%%)\n"),(INODES-free), 100*(INODES-free)/INODES); for (i=FIRSTZONE,free=0 ; i < ZONES ; i++) if (!zone_in_use(i)) free++; - printf("%6ld zones used (%ld%%)\n",(ZONES-free), + printf(_("%6ld zones used (%ld%%)\n"),(ZONES-free), 100*(ZONES-free)/ZONES); - printf("\n%6d regular files\n" + printf(_("\n%6d regular files\n" "%6d directories\n" "%6d character device files\n" "%6d block device files\n" "%6d links\n" "%6d symbolic links\n" "------\n" - "%6d files\n", + "%6d files\n"), regular,directory,chardev,blockdev, links-2*directory+1,symlinks,total-2*directory+1); } if (changed) { write_tables(); - printf( "----------------------------\n" + printf(_( "----------------------------\n" "FILE SYSTEM HAS BEEN CHANGED\n" - "----------------------------\n"); + "----------------------------\n")); for (count=0 ; count<3 ; count++) sync(); } diff --git a/disk-utils/mkfs.8 b/disk-utils/mkfs.8 index 2dd61648..260b4e09 100644 --- a/disk-utils/mkfs.8 +++ b/disk-utils/mkfs.8 @@ -23,8 +23,14 @@ mkfs \- build a Linux file system is used to build a Linux file system on a device, usually a hard disk partition. .I filesys -is either the device name (e.g. /dev/hda1, /dev/sdb2) or -the mount point (e.g. /, /usr, /home) for the file system. +is either the device name (e.g. +.IR /dev/hda1 , +.IR /dev/sdb2 ) +or the mount point (e.g. +.IR / , +.IR /usr , +.IR /home ) +for the file system. .I blocks is the number of blocks to be used for the file system. .PP @@ -38,9 +44,18 @@ is simply a front-end for the various file system builders (\fBmkfs\fR.\fIfstype\fR) available under Linux. The file system-specific builder is searched for in a number -of directories like /sbin, /sbin/fs, /sbin/fs.d, /etc/fs, /etc +of directories like perhaps +.IR /sbin , +.IR /sbin/fs , +.IR /sbin/fs.d , +.IR /etc/fs , +.I /etc (the precise list is defined at compile time but at least -contains /sbin and /sbin/fs), and finally in the directories +contains +.I /sbin +and +.IR /sbin/fs ), +and finally in the directories listed in the PATH enviroment variable. Please see the file system-specific builder manual pages for further details. @@ -93,8 +108,12 @@ Ron Sommeling (sommel@sci.kun.nl) The manual page was shamelessly adapted from Remy Card's version for the ext2 file system. .SH SEE ALSO +.BR fs (5), +.BR badblocks (8), .BR fsck (8), -.BR mkfs.minix (8), -.BR mkfs.ext (8), +.BR mkdosfs (8), +.BR mke2fs (8), .BR mkfs.ext2 (8), -.BR mkfs.xiafs (8). +.BR mkfs.minix (8), +.BR mkfs.msdos (8), +.BR mkfs.xiafs (8) diff --git a/disk-utils/mkfs.c b/disk-utils/mkfs.c index ba293e93..9ea27a50 100644 --- a/disk-utils/mkfs.c +++ b/disk-utils/mkfs.c @@ -10,6 +10,9 @@ * * Mon Jul 1 18:52:58 1996: janl@math.uio.no (Nicolai Langfeldt): * Incorporated fix by Jonathan Kamens + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ @@ -19,9 +22,10 @@ #include #include #include +#include "nls.h" - -#define VERSION "1.10" +#include "../version.h" +#define VERSION UTIL_LINUX_VERSION #ifndef DEFAULT_FSTYPE # define DEFAULT_FSTYPE "ext2" @@ -38,6 +42,10 @@ int main(int argc, char *argv[]) int i, more = 0, verbose = 0; char *oldpath, *newpath; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + /* Check commandline options. */ opterr = 0; while ((more == 0) && ((i = getopt(argc, argv, "Vt:")) != EOF)) @@ -55,7 +63,7 @@ int main(int argc, char *argv[]) } if (optind == argc) { fprintf(stderr, - "Usage: mkfs [-V] [-t fstype] [fs-options] device [size]\n"); + _("Usage: mkfs [-V] [-t fstype] [fs-options] device [size]\n")); return -1; } @@ -69,7 +77,7 @@ int main(int argc, char *argv[]) oldpath = "/bin"; newpath = (char *) malloc(strlen(oldpath) + sizeof(SEARCH_PATH) + 2); if (!newpath) { - fputs("mkfs: out of memory\n", stderr); + fprintf(stderr, _("%s: Out of memory!\n"), "mkfs"); exit(1); } sprintf(newpath, "%s:%s\n", SEARCH_PATH, oldpath); @@ -78,7 +86,7 @@ int main(int argc, char *argv[]) argv[--optind] = progname; if (verbose) { - puts("mkfs version " VERSION " (" __DATE__ ")"); + puts(_("mkfs version " VERSION " (" __DATE__ ")")); i = optind; while (argv[i]) printf("%s ", argv[i++]); diff --git a/disk-utils/mkfs.minix.8 b/disk-utils/mkfs.minix.8 index 9ff75321..6a9c7931 100644 --- a/disk-utils/mkfs.minix.8 +++ b/disk-utils/mkfs.minix.8 @@ -48,11 +48,8 @@ Check the device for bad blocks before creating the file system. If any are found, the count is printed. .TP .BI \-n " namelength" -Specify the maximum length of filenames. No space is allowed between the -.B \-n -and the -.IR namelength. Currently, the only allowable -values are 14 and 30. +Specify the maximum length of filenames. +Currently, the only allowable values are 14 and 30. .B 30 is the default. .TP .BI \-i " inodecount" @@ -77,9 +74,10 @@ Operational error .IP 16 Usage or syntax error .SH "SEE ALSO" +.BR mkfs (8), .BR fsck (8), -.BR mkefs (8), -.BR efsck (8), +.BR mke2fs (8), +.BR e2fsck (8), .BR reboot (8) .\" .SH AUTHORS .\" Linus Torvalds (torvalds@cs.helsinki.fi). diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c index c34da532..b05960b2 100644 --- a/disk-utils/mkfs.minix.c +++ b/disk-utils/mkfs.minix.c @@ -70,10 +70,14 @@ #include #include #include +#include #include #include +#include "nls.h" +#include "../version.h" + #ifdef MINIX2_SUPER_MAGIC2 #define HAVE_MINIX2 1 #endif @@ -170,8 +174,19 @@ volatile void fatal_error(const char * fmt_string,int status) exit(status); } -#define usage() fatal_error("Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n",16) -#define die(str) fatal_error("%s: " str "\n",8) +volatile void die(char *str) { + fprintf(stderr, "%s: %s\n", program_name, str); + exit(8); +} + +volatile void usage() +{ + fprintf(stderr, "%s (%s)\n", program_name, util_linux_version); + fprintf(stderr, + _("Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n"), + program_name); + exit(16); +} /* * Check to make certain that our new filesystem won't be created on @@ -192,7 +207,7 @@ static void check_mount(void) if (!mnt) return; - die("%s is mounted; will not make a filesystem here!"); + die(_("%s is mounted; will not make a filesystem here!")); } static long valid_offset (int fd, int offset) @@ -229,7 +244,7 @@ static int count_blocks (int fd) static int get_size(const char *file) { int fd; - int size; + long size; fd = open(file, O_RDWR); if (fd < 0) { @@ -253,28 +268,28 @@ void write_tables(void) Super.s_state &= ~MINIX_ERROR_FS; if (lseek(DEV, 0, SEEK_SET)) - die("seek to boot block failed in write_tables"); + die(_("seek to boot block failed in write_tables")); if (512 != write(DEV, boot_block_buffer, 512)) - die("unable to clear boot sector"); + die(_("unable to clear boot sector")); if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) - die("seek failed in write_tables"); + die(_("seek failed in write_tables")); if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) - die("unable to write super-block"); + die(_("unable to write super-block")); if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE)) - die("unable to write inode map"); + die(_("unable to write inode map")); if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE)) - die("unable to write zone map"); + die(_("unable to write zone map")); if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE)) - die("unable to write inodes"); + die(_("unable to write inodes")); } void write_block(int blk, char * buffer) { if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET)) - die("seek failed in write_block"); + die(_("seek failed in write_block")); if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) - die("write failed in write_block"); + die(_("write failed in write_block")); } int get_free_block(void) @@ -282,7 +297,7 @@ int get_free_block(void) int blk; if (used_good_blocks+1 >= MAX_GOOD_BLOCKS) - die("too many bad blocks"); + die(_("too many bad blocks")); if (used_good_blocks) blk = good_blocks_table[used_good_blocks-1]+1; else @@ -290,7 +305,7 @@ int get_free_block(void) while (blk < ZONES && zone_in_use(blk)) blk++; if (blk >= ZONES) - die("not enough good blocks"); + die(_("not enough good blocks")); good_blocks_table[used_good_blocks] = blk; used_good_blocks++; return blk; @@ -356,7 +371,7 @@ void make_bad_inode(void) goto end_bad; } } - die("too many bad blocks"); + die(_("too many bad blocks")); end_bad: if (ind) write_block(ind, (char *) ind_block); @@ -407,7 +422,7 @@ make_bad_inode2 (void) } } /* Could make triple indirect block here */ - die ("too many bad blocks"); + die (_("too many bad blocks")); end_bad: if (ind) write_block (ind, (char *) ind_block); @@ -499,7 +514,7 @@ void setup_tables(void) inode_map = malloc(IMAPS * BLOCK_SIZE); zone_map = malloc(ZMAPS * BLOCK_SIZE); if (!inode_map || !zone_map) - die("unable to allocate buffers for maps"); + die(_("unable to allocate buffers for maps")); memset(inode_map,0xff,IMAPS * BLOCK_SIZE); memset(zone_map,0xff,ZMAPS * BLOCK_SIZE); for (i = FIRSTZONE ; i ZONES) try = ZONES-currently_testing; @@ -576,13 +591,15 @@ void check_blocks(void) if (got == try) continue; if (currently_testing < FIRSTZONE) - die("bad blocks before data-area: cannot make fs"); + die(_("bad blocks before data-area: cannot make fs")); mark_zone(currently_testing); badblocks++; currently_testing++; } - if (badblocks) - printf("%d bad block%s\n",badblocks,(badblocks>1)?"s":""); + if (badblocks > 1) + printf(_("%d bad blocks\n"), badblocks); + else if (badblocks == 1) + printf(_("one bad block\n")); } void get_list_blocks(filename) @@ -594,20 +611,20 @@ char *filename; listfile=fopen(filename,"r"); if(listfile == (FILE *)NULL) { - die("can't open file of bad blocks"); + die(_("can't open file of bad blocks")); } while(!feof(listfile)) { fscanf(listfile,"%ld\n", &blockno); mark_zone(blockno); badblocks++; } - if(badblocks) { - printf("%d bad block%s\n", badblocks, (badblocks>1)?"s":""); - } + if(badblocks > 1) + printf(_("%d bad blocks\n"), badblocks); + else if (badblocks == 1) + printf(_("one bad block\n")); } int main(int argc, char ** argv) - { int i; char * tmp; @@ -617,66 +634,59 @@ int main(int argc, char ** argv) if (argc && *argv) program_name = *argv; if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad inode size"); + die(_("bad inode size")); #ifdef HAVE_MINIX2 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad inode size"); + die(_("bad inode size")); #endif - while (argc-- > 1) { - argv++; - if (argv[0][0] != '-') { - if (device_name) { - BLOCKS = strtol(argv[0],&tmp,0); - if (*tmp) { - printf("strtol error: number of" - " blocks not specified"); + opterr = 0; + while ((i = getopt(argc, argv, "ci:l:n:v")) != EOF) + switch (i) { + case 'c': + check=1; break; + case 'i': + req_nr_inodes = (unsigned long) atol(optarg); + break; + case 'l': + listfile = optarg; break; + case 'n': + i = strtoul(optarg,&tmp,0); + if (*tmp) usage(); - } - } else - device_name = argv[0]; - } else { - if(argv[0][1] == 'l') { - listfile = argv[1]; - argv++; - if (!(argc--)) + if (i == 14) + magic = MINIX_SUPER_MAGIC; + else if (i == 30) + magic = MINIX_SUPER_MAGIC2; + else usage(); - } else { - if(argv[0][1] == 'i') { - req_nr_inodes - = (unsigned long)atol(argv[1]); - argv++; - if (!(argc--)) - usage(); - } else while (*(++argv[0])) { - switch (argv[0][0]) { - case 'c': check=1; break; - case 'n': - i = strtoul(argv[0]+1,&tmp,0); - if (*tmp) - usage(); - argv[0][1] = '\0'; - if (i == 14) - magic = MINIX_SUPER_MAGIC; - else if (i == 30) - magic = MINIX_SUPER_MAGIC2; - else - usage(); - namelen = i; - dirsize = i+2; - break; - case 'v': + namelen = i; + dirsize = i+2; + break; + case 'v': #ifdef HAVE_MINIX2 - version2 = 1; + version2 = 1; #else - fatal_error("%s: not compiled with minix v2 support\n",-1); + fatal_error(_("%s: not compiled with minix v2 support\n"),-1); #endif - break; - default: usage(); - } - } - } + break; + default: + usage(); } + argc -= optind; + argv += optind; + if (argc > 0 && !device_name) { + device_name = argv[0]; + argc--; + argv++; + } + if (argc > 0) { + BLOCKS = strtol(argv[0],&tmp,0); + if (*tmp) { + printf(_("strtol error: number of blocks not specified")); + usage(); + } } + if (device_name && !BLOCKS) BLOCKS = get_size (device_name) / 1024; if (!device_name || BLOCKS<10) { @@ -704,13 +714,13 @@ int main(int argc, char ** argv) strcpy(tmp+2,".badblocks"); DEV = open(device_name,O_RDWR ); if (DEV<0) - die("unable to open %s"); + die(_("unable to open %s")); if (fstat(DEV,&statbuf)<0) - die("unable to stat %s"); + die(_("unable to stat %s")); if (!S_ISBLK(statbuf.st_mode)) check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) - die("will not try to make filesystem on '%s'"); + die(_("will not try to make filesystem on '%s'")); setup_tables(); if (check) check_blocks(); diff --git a/disk-utils/mkswap.8 b/disk-utils/mkswap.8 index 2df606c5..c16a8938 100644 --- a/disk-utils/mkswap.8 +++ b/disk-utils/mkswap.8 @@ -3,7 +3,7 @@ .\" May be distributed under the GNU General Public License .\" Rewritten for 2.1.117, aeb, 981010. .\" -.TH MKSWAP 8 "1 December 1998" "Linux 2.1.117" "Linux Programmer's Manual" +.TH MKSWAP 8 "25 March 1999" "Linux 2.2.4" "Linux Programmer's Manual" .SH NAME mkswap \- set up a Linux swap area .SH SYNOPSIS @@ -36,7 +36,8 @@ The parameter is superfluous but retained for backwards compatibility. (It specifies the desired size of the swap area in 1024-byte blocks. .B mkswap -will use the entire partition or file if it is omitted.) +will use the entire partition or file if it is omitted. +Specifying it is unwise - a typo may destroy your disk.) 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 @@ -61,8 +62,9 @@ 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. +The maximum useful size of a swap area now depends on the architecture. +It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, +128GB on alpha and 3TB on sparc64. 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 @@ -103,6 +105,9 @@ before creating the swap area. If any are found, the count is printed. .TP .B \-f +Force - go ahead even if the command is stupid. +This allows the creation of a swap area larger than the file +or partition it resides on. On SPARC, force creation of the swap area. Without this option .B mkswap diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index b3402366..ef5f58c1 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -8,7 +8,7 @@ /* * 20.12.91 - time began. Got VM working yesterday by doing this by hand. * - * Usuage: mkswap [-c] [-vN] [-f] device [size-in-blocks] + * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks] * * -c for readability checking. (Use it unless you are SURE!) * -vN for swap areas version N. (Only N=0,1 known today.) @@ -23,6 +23,11 @@ * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. * * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. + * V1_MAX_PAGES fixes, jj, 990325. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -34,6 +39,8 @@ #include #include #include /* for PAGE_SIZE and PAGE_SHIFT */ + /* we also get PAGE_SIZE via getpagesize() */ +#include "nls.h" #ifndef _IO /* pre-1.3.45 */ @@ -91,7 +98,7 @@ init_signature_page() { #ifdef PAGE_SIZE if (pagesize != PAGE_SIZE) - fprintf(stderr, "Assuming pages of size %d\n", pagesize); + fprintf(stderr, _("Assuming pages of size %d\n"), pagesize); #endif signature_page = (int *) malloc(pagesize); memset(signature_page,0,pagesize); @@ -106,7 +113,48 @@ write_signature(char *sig) { } #define V0_MAX_PAGES (8 * (pagesize - 10)) -#define V1_MAX_PAGES ((0x7fffffff / pagesize) - 1) +/* Before 2.2.0pre9 */ +#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1) +/* Since 2.2.0pre9: + error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL)) + with variations on + #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + #define SWP_OFFSET(entry) ((entry) >> 8) + on the various architectures. Below the result - yuk. + + Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2 + i386 2^12 o<<8 e>>8 1<<24 1<<19 + mips 2^12 o<<15 e>>15 1<<17 1<<19 + alpha 2^13 o<<40 e>>40 1<<24 1<<18 + m68k 2^12 o<<12 e>>12 1<<20 1<<19 + sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18} + sparc64 2^13 o<<13 e>>13 1<<51 1<<18 + ppc 2^12 o<<8 e>>8 1<<24 1<<19 + armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16} + armv 2^12 o<<9 e>>9 1<<23 1<<19 + + assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere. + + The bad part is that we need to know this since the kernel will + refuse a swap space if it is too large. +*/ +/* patch from jj - why does this differ from the above? */ +#if defined(__alpha__) +#define V1_MAX_PAGES ((1 << 24) - 1) +#elif defined(__mips__) +#define V1_MAX_PAGES ((1 << 17) - 1) +#elif defined(__sparc_v9__) +#define V1_MAX_PAGES ((3 << 29) - 1) +#elif defined(__sparc__) +#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1)) +#else +#define V1_MAX_PAGES V1_OLD_MAX_PAGES +#endif +/* man page now says: +The maximum useful size of a swap area now depends on the architecture. +It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, +128GB on alpha and 3TB on sparc64. +*/ #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) @@ -137,8 +185,8 @@ void fatal_error(const char * fmt_string) exit(1); } -#define usage() fatal_error("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n") -#define die(str) fatal_error("%s: " str "\n") +#define usage() fatal_error(_("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n")) +#define die(str) fatal_error(_("%s: " str "\n")) void page_ok(int page) { @@ -182,8 +230,10 @@ check_blocks(void) { } page_ok(current_page++); } - if (badpages) - printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); + if (badpages == 1) + printf(_("one bad page\n")); + else if (badpages > 1) + printf(_("%d bad pages\n"), badpages); } static long valid_offset (int fd, int offset) @@ -218,11 +268,11 @@ find_size (int fd) } /* return size in pages, to avoid integer overflow */ -static int +static long get_size(const char *file) { int fd; - int size; + long size; fd = open(file, O_RDONLY); if (fd < 0) { @@ -243,11 +293,17 @@ int main(int argc, char ** argv) { char * tmp; struct stat statbuf; + int sz; int maxpages; int goodpages; int offset; int force = 0; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc && *argv) program_name = *argv; @@ -281,12 +337,20 @@ int main(int argc, char ** argv) } if (!device_name) { fprintf(stderr, - "%s: error: Nowhere to set up swap on?\n", + _("%s: error: Nowhere to set up swap on?\n"), program_name); usage(); } + sz = get_size(device_name); if (!PAGES) { - PAGES = get_size(device_name); + PAGES = sz; + } else if (PAGES > sz && !force) { + fprintf(stderr, + _("%s: error: " + "size %ld is larger than device size %d\n"), + program_name, + PAGES*(pagesize/1024), sz*(pagesize/1024)); + exit(1); } if (version == -1) { @@ -300,20 +364,32 @@ int main(int argc, char ** argv) version = 1; } if (version != 0 && version != 1) { - fprintf(stderr, "%s: error: unknown version %d\n", + 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", + _("%s: error: swap area needs to be at least %ldkB\n"), program_name, (long)(10 * pagesize / 1024)); usage(); } +#if 0 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); +#else + if (!version) + maxpages = V0_MAX_PAGES; + else if (linux_version_code() >= MAKE_VERSION(2,2,1)) + maxpages = V1_MAX_PAGES; + else { + maxpages = V1_OLD_MAX_PAGES; + if (maxpages > V1_MAX_PAGES) + maxpages = V1_MAX_PAGES; + } +#endif if (PAGES > maxpages) { PAGES = maxpages; - fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", + fprintf(stderr, _("%s: warning: truncating swap area to %ldkB\n"), program_name, PAGES * pagesize / 1024); } @@ -340,11 +416,11 @@ int main(int argc, char ** argv) for (sum = 0; q >= (unsigned short *) buffer;) sum ^= *q--; if (!sum) { - fprintf(stderr, "\ + 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", +the -f option to force it.\n"), program_name, device_name); exit(1); } @@ -365,7 +441,7 @@ the -f option to force it.\n", goodpages = PAGES - badpages - 1; if (goodpages <= 0) die("Unable to set up swap-space: unreadable"); - printf("Setting up swapspace version %d, size = %ld bytes\n", + printf(_("Setting up swapspace version %d, size = %ld bytes\n"), version, (long)(goodpages*pagesize)); write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); diff --git a/disk-utils/setfdprm.c b/disk-utils/setfdprm.c index 62234f3a..7c2b0dc3 100644 --- a/disk-utils/setfdprm.c +++ b/disk-utils/setfdprm.c @@ -1,6 +1,10 @@ /* setfdprm.c - Sets user-provided floppy disk parameters, re-activates autodetection and switches diagnostic messages. */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + #include #include #include @@ -10,6 +14,7 @@ #include #include #include +#include "nls.h" #define FDPRMFILE "/etc/fdprm" #define MAXLINE 200 @@ -22,7 +27,7 @@ static int convert(char *arg) result = strtol(arg,&end,0); if (!*end) return (int) result; - fprintf(stderr,"Invalid number: %s\n",arg); + fprintf(stderr,_("Invalid number: %s\n"),arg); exit(1); } @@ -72,7 +77,7 @@ static void find_params(int cmd,int fd,char *name) if (sscanf(start,"%s %s %s %s %s %s %s %s %s %s",this,param[0], param[1],param[2],param[3],param[4],param[5],param[6],param[7], param[8]) != 10) { - fprintf(stderr,"Syntax error: '%s'\n",line); + fprintf(stderr,_("Syntax error: '%s'\n"),line); exit(1); } if (!strcmp(this,name)) { @@ -82,7 +87,7 @@ static void find_params(int cmd,int fd,char *name) } } } - fprintf(stderr,"No such parameter set: '%s'\n",name); + fprintf(stderr,_("No such parameter set: '%s'\n"),name); exit(1); } @@ -92,13 +97,13 @@ static void usage(char *name) char *this; if ((this = strrchr(name,'/')) != NULL) name = this+1; - fprintf(stderr,"usage: %s [ -p ] dev name\n",name); - fprintf(stderr," %s [ -p ] dev size sect heads tracks stretch \ -gap rate spec1 fmt_gap\n",name); + fprintf(stderr,_("usage: %s [ -p ] dev name\n"),name); + fprintf(stderr,_(" %s [ -p ] dev size sect heads tracks stretch \ +gap rate spec1 fmt_gap\n"),name); #ifdef FDMEDCNG - fprintf(stderr," %s [ -c | -y | -n | -d ] dev\n",name); + fprintf(stderr,_(" %s [ -c | -y | -n | -d ] dev\n"),name); #else - fprintf(stderr," %s [ -c | -y | -n ] dev\n",name); + fprintf(stderr,_(" %s [ -c | -y | -n ] dev\n"),name); #endif exit(1); } @@ -110,6 +115,10 @@ main(int argc,char **argv) unsigned int cmd; char *name; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + name = argv[0]; if (argc < 3) usage(name); cmd = FDSETPRM; diff --git a/fdisk/Makefile b/fdisk/Makefile index e5415acd..873b2850 100644 --- a/fdisk/Makefile +++ b/fdisk/Makefile @@ -3,24 +3,33 @@ # Revised: Fri Oct 6 21:02:21 1995 by r.faith@ieee.org # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) # - +include ../make_include include ../MCONFIG MAN8= SBIN= +CFDISK=cfdisk +NOTMADE= -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 +ifneq "$(HAVE_SLANG)" "yes" +ifneq "$(HAVE_NCURSES)" "yes" +CFDISK= +NOTMADE=cfdisk endif +endif + +ifeq "$(CPU)" "m68k" +# It seems the m68k people do not want *fdisk else -MAN8:=$(MAN8) fdisk.8 SBIN:=$(SBIN) fdisk +MAN8:=$(MAN8) fdisk.8 +ifneq "$(CPU)" "sparc" +SBIN:=$(SBIN) $(CFDISK) sfdisk +MAN8:=$(MAN8) cfdisk.8 sfdisk.8 +endif endif -all: $(SBIN) +all: $(SBIN) $(NOTMADE) cfdisk.o: cfdisk.c ifeq "$(HAVE_SLANG)" "yes" @@ -33,12 +42,12 @@ else endif endif -cfdisk: cfdisk.o llseek.o +cfdisk: cfdisk.o llseek.o i386_sys_types.o ifeq "$(HAVE_SLANG)" "yes" $(CC) $(LDFLAGS) $^ -o $@ $(LIBSLANG) else ifeq "$(HAVE_NCURSES)" "yes" - $(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES) -lm + $(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES) else @echo $@ not made since it requires ncurses or slang endif @@ -50,12 +59,14 @@ activate: sfdisk ln -s sfdisk activate fdisk: fdisk.o llseek.o fdiskbsdlabel.o fdisksgilabel.o fdisksunlabel.o \ - fdiskaixlabel.o + fdiskaixlabel.o i386_sys_types.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 +fdisk.o cfdisk.o sfdisk.o fdiskbsdlabel.o fdisksunlabel.o \ + fdisksgilabel.o fdiskaixlabel.o i386_sys_types.o: common.h +sfdisk: sfdisk.o i386_sys_types.o install: all $(INSTALLDIR) $(SBINDIR) @@ -65,4 +76,4 @@ install: all .PHONY: clean clean: - -rm -f *.o *~ core $(SBIN) + -rm -f *.o *~ core $(SBIN) addpart delpart diff --git a/fdisk/README.fdisk b/fdisk/README.fdisk index 86b18252..b02d6aa2 100644 --- a/fdisk/README.fdisk +++ b/fdisk/README.fdisk @@ -369,7 +369,7 @@ unless there are sectors available inside the extended partition. If space is available, you are prompted for the first cylinder: - First sector ([237]-977): _ + First cylinder ([237]-977): _ The limits are the lowest and the highest cylinders in which sectors are available in the appropriate part of the disk. The square-bracketed diff --git a/fdisk/addpart.c b/fdisk/addpart.c new file mode 100644 index 00000000..11d4305b --- /dev/null +++ b/fdisk/addpart.c @@ -0,0 +1,40 @@ +/* very primitive wrapper around the `add partition' ioctl */ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv){ + int fd; + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + + if (argc != 5) { + fprintf(stderr, + "usage: %s diskdevice partitionnr start length\n", + argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDONLY)) < 0) { + perror(argv[1]); + exit(1); + } + p.pno = atoi(argv[2]); + p.start = 512 * ((long long) atol(argv[3])); + p.length = 512 * ((long long) atol(argv[4])); + p.devname[0] = 0; + p.volname[0] = 0; + a.op = BLKPG_ADD_PARTITION; + a.flags = 0; + a.datalen = sizeof(p); + a.data = &p; + + if (ioctl(fd, BLKPG, &a) == -1) { + perror("BLKPG"); + exit(1); + } + + return 0; +} diff --git a/fdisk/cfdisk.8 b/fdisk/cfdisk.8 index c8391af2..09dd5470 100644 --- a/fdisk/cfdisk.8 +++ b/fdisk/cfdisk.8 @@ -15,13 +15,14 @@ .SH NAME cfdisk \- Curses based disk partition table manipulator for Linux .SH SYNOPSIS -.BI "cfdisk [ \-avz ] [ \-c " cylinders " ] [ \-h " heads " ]" +.BI "cfdisk [ \-agvz ] [ \-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 +is a curses based program for partitioning any hard disk drive. +Typical values of the .I device -can be any one of the following: +argument are: .sp .nf .RS @@ -34,14 +35,28 @@ can be any one of the following: .RE .fi +In order to write the partition table .B cfdisk -first tries to read the geometry of the hard disk. If it fails, an -error message is displayed and +needs something called the `geometry' of the disk: the number +of `heads' and the number of `sectors per track'. Linux does not +use any geometry, so if the disk will not be accessed by other +operating systems, you can safely accept the defaults that .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, +chooses for you. The geometry used by +.B cfdisk +is found as follows. First the partition table is examined, +to see what geometry was used by the previous program that +changed it. If the partition table is empty, or contains garbage, +or does not point at a consistent geometry, the kernel is +asked for advice. If nothing works 255 heads and 63 sectors/track +is assumed. The geometry can be overridden on the command line +or by use of the `g' command. When partitioning an empty large modern +disk, picking 255 heads and 63 sectors/track is always a good idea. +There is no need to set the number of cylinders, since +.B cfdisk +knows the disk size. + +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 @@ -368,6 +383,10 @@ key to return to the main command line. Use an arrow cursor instead of reverse video for highlighting the current partition. .TP +.B \-g +Do not use the geometry given by the disk driver, but try to +guess a geometry from the partition table. +.TP .B \-v Print the version number and copyright. .TP diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index 96ddbbf2..4fe759b6 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -29,15 +29,24 @@ * >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-n: aeb@cwi.nl + * Versions 0.8e-p: aeb@cwi.nl + * Rebaptised 2.9p, following util-linux versioning. + * * 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]. + * 1: command line error, out of memory + * 2: hardware problems [Cannot open/seek/read/write disk drive]. + * 3: ioctl(fd, HDIO_GETGEO,...) failed. (Probably it is not a disk.) + * 4: bad partition table on disk. [Bad primary/logical partition]. + * + * Sat, 23 Jan 1999 19:34:45 +0100 + * Internationalized + provided initial French translation. + * Sat Mar 20 09:26:34 EST 1999 + * Some more i18n. + * Sun Jul 18 03:19:42 MEST 1999 + * Terabyte-sized disks. * ****************************************************************************/ @@ -66,7 +75,10 @@ #include #include #include -#include /* for BLKRRPART */ +#include /* for BLKRRPART, BLKGETSIZE */ + +#include "nls.h" +#include "common.h" #if defined(__GNUC__) || defined(HAS_LONG_LONG) typedef long long ext2_loff_t; @@ -77,17 +89,25 @@ typedef long ext2_loff_t; extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, unsigned int origin); -#define VERSION "0.8n" +#include "../version.h" +#define VERSION UTIL_LINUX_VERSION #define DEFAULT_DEVICE "/dev/hda" #define ALTERNATE_DEVICE "/dev/sda" +/* With K=1024 we have `binary' megabytes, gigabytes, etc. + Some misguided hackers like that. + With K=1000 we have MB and GB that follow the standards + [SI, ATA, IEEE etc] and the disk manufacturers and the law. */ +#define K 1000 + #define LINE_LENGTH 80 #define MAXIMUM_PARTS 60 #define SECTOR_SIZE 512 -#define MAX_CYLINDERS 65535 +#define MAX_CYLINDERS 65535 /* there is no maximum anymore */ + /* the kernel max is 65535 */ #define MAX_HEADS 255 #define MAX_SECTORS 63 @@ -105,55 +125,48 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, #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 READONLY_WARN "Opened disk read-only - you have no permission to write" -#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 NOT_DOS_MBR_BOOTABLE "Not precisely one primary partition is bootable. DOS MBR cannot boot this." +/* There used to be defined error messages here. However, it turns out + * that gettext cannot handle constructions like + * + * #define ADD_EXISTS _("This partition is already in use") + * ... + * print_warning(ADD_EXISTS); + * + * So, now the messages are spread over the source again. + * Another thing which gettext cannot cope with are multi-line strings: + * + * printf("Usage: + * Print version: + * cfdisk -v + * Print partition table: + * cfdisk -P{r|s|t} device + * "); + * + * (This is a commonly used gnu extension of the C syntax, but not ANSI-C.) + * Another reason to uglify the source a little. + */ + #define PRI_OR_LOG -1 #define PRIMARY -2 #define LOGICAL -3 -#define COL_ID_WIDTH 20 +#define COL_ID_WIDTH 25 #define CR '\015' #define ESC '\033' #define DEL '\177' #define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' +#define TAB '\011' +#define REDRAWKEY '\014' /* ^L */ +#define UPKEY '\020' /* ^P */ +#define DOWNKEY '\016' /* ^N */ /* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 +#define GIGABYTES 1 +#define MEGABYTES 2 +#define SECTORS 3 +#define CYLINDERS 4 #define GS_DEFAULT -1 #define GS_ESCAPE -2 @@ -168,24 +181,6 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, #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 is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ - (x) == LINUX_EXTENDED) - -#define is_dos_partition(x) ((x) == 1 || (x) == 4 || (x) == 6) -#define may_have_dos_label(x) (is_dos_partition(x) \ - || (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 */ @@ -199,6 +194,58 @@ struct partition { unsigned char size4[4]; /* nr of sectors in partition */ }; +int heads = 0; +int sectors = 0; +int cylinders = 0; +int cylinder_size = 0; /* heads * sectors */ +int total_size = 0; /* actual_size rounded down */ +long actual_size = 0; /* set using ioctl */ + /* explicitly given user values */ +int user_heads = 0, user_sectors = 0, user_cylinders = 0; + /* kernel values; ignore the cylinders */ +int kern_heads = 0, kern_sectors = 0; + /* partition-table derived values */ +int pt_heads = 0, pt_sectors = 0; + + +void +set_hsc0(unsigned char *h, unsigned char *s, int *c, int sector) { + if (sector >= 1024*cylinder_size) + sector = 1024*cylinder_size - 1; + *s = sector % sectors + 1; + sector /= sectors; + *h = sector % heads; + sector /= heads; + *c = sector; +} + +void +set_hsc(unsigned char *h, unsigned char *s, unsigned char *c, int sector) { + int cc; + + set_hsc0(h, s, &cc, sector); + *c = cc & 0xFF; + *s |= (cc >> 2) & 0xC0; +} + +void +set_hsc_begin(struct partition *p, int sector) { + set_hsc(& p->head, & p->sector, & p->cyl, sector); +} + +void +set_hsc_end(struct partition *p, int sector) { + set_hsc(& p->end_head, & p->end_sector, & p->end_cyl, sector); +} + +#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ + (x) == LINUX_EXTENDED) + +#define is_dos_partition(x) ((x) == 1 || (x) == 4 || (x) == 6) +#define may_have_dos_label(x) (is_dos_partition(x) \ + || (x) == 7 || (x) == 0xb || (x) == 0xc || (x) == 0xe \ + || (x) == 0x11 || (x) == 0x14 || (x) == 0x16 || (x) == 0x17) + /* start_sect and nr_sects are stored little endian on all machines */ /* moreover, they are not aligned correctly */ void @@ -266,9 +313,6 @@ typedef struct { char *disk_device = DEFAULT_DEVICE; int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; int changed = FALSE; int opened = FALSE; int opentype; @@ -286,6 +330,7 @@ __sighandler_t old_SIGINT, old_SIGTERM; int arrow_cursor = FALSE; int display_units = MEGABYTES; int zero_table = FALSE; +int use_partition_table_geometry = FALSE; int print_only = 0; /* Curses screen information */ @@ -297,7 +342,7 @@ int NUM_ON_SCREEN = 1; /* Y coordinates */ int HEADER_START = 0; -int DISK_TABLE_START = 5; +int DISK_TABLE_START = 6; int WARNING_START = 23; int COMMAND_LINE_Y = 21; @@ -310,55 +355,24 @@ int LABEL_START = 54; 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", - [DOS_EXTENDED]= "Extended", - [LINUX_EXTENDED] = "Linux extended", - [0x01] = "DOS FAT12", - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x04] = "DOS FAT16", - [0x06] = "DOS FAT16 (big)", - [OS2_OR_NTFS] = "OS/2 HPFS or NTFS", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x0A] = "OS/2 Boot Manager", - [0x0B] = "Win95 FAT32", - [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", - [0x63] = "GNU HURD", - [0x64] = "Novell Netware 286", - [0x65] = "Novell Netware 386", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xA5] = "BSD/386", - [0xA6] = "OpenBSD", - [0xA7] = "NEXTSTEP", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xEB] = "BeOS fs", - [0xF2] = "DOS secondary", - [0xFF] = "BBT" -}; +void die_x(int ret); +void draw_screen(void); + +/* Guaranteed alloc */ +void * +xmalloc (size_t size) { + void *t; + + if (size == 0) + return NULL; + + t = malloc (size); + if (t == NULL) { + fprintf (stderr, _("%s: Out of memory!\n"), "cfdisk"); + die_x(1); + } + return t; +} /* Some libc's have their own basename() */ char *my_basename(char *devname) @@ -367,28 +381,37 @@ char *my_basename(char *devname) return s ? s+1 : devname; } +char *partition_type_name(unsigned char type) +{ + struct systypes *s = i386_sys_types; + + while(s->name && s->type != type) + s++; + return s->name; +} + char *partition_type_text(int i) { if (p_info[i].id == UNUSABLE) - return "Unusable"; + return _("Unusable"); else if (p_info[i].id == FREE_SPACE) - return "Free Space"; + return _("Free Space"); else if (p_info[i].id == LINUX) { if (!strcmp(p_info[i].fstype, "ext2")) - return "Linux ext2"; + return _("Linux ext2"); else - return "Linux"; + return _("Linux"); } else if (p_info[i].id == OS2_OR_NTFS) { if (!strncmp(p_info[i].fstype, "HPFS", 4)) - return "OS/2 HPFS"; + return _("OS/2 HPFS"); else if (!strncmp(p_info[i].ostype, "OS2", 3)) - return "OS/2 IFS"; + return _("OS/2 IFS"); else if (!p_info[i].ostype) return p_info[i].ostype; else - return "NTFS"; + return _("NTFS"); } else - return partition_type[p_info[i].id]; + return partition_type_name(p_info[i].id); } void fdexit(int ret) @@ -397,13 +420,13 @@ void fdexit(int ret) 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, _("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" + 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" ); + "page for additional information.\n") ); } exit(ret); @@ -494,23 +517,25 @@ void print_warning(char *s) } } -void die_x(int ret); - void fatal(char *s, int ret) { - char str[LINE_LENGTH]; + char *err = _("FATAL ERROR"); if (curses_started) { - sprintf(str, "FATAL ERROR: %s", s); + char *str = xmalloc(strlen(s) + strlen(err) + 10); + /* snprintf does not compile on all libc's */ + sprintf(str, "%s: %s", err, s); + if (strlen(str) > COLS) + str[COLS] = 0; mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); + sprintf(str, _("Press any key to exit cfdisk")); mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); putchar(BELL); /* CTRL-G */ refresh(); (void)getch(); die_x(ret); } else { - fprintf(stderr, "FATAL ERROR: %s\n", s); + fprintf(stderr, "%s: %s\n", err, s); exit(ret); } } @@ -539,17 +564,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, 2); + fatal(_("Cannot seek on disk drive"), 2); if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ, 2); + fatal(_("Cannot read disk drive"), 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, 2); + fatal(_("Cannot seek on disk drive"), 2); if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE, 2); + fatal(_("Cannot write disk drive"), 2); } void dos_copy_to_info(char *to, int tosz, char *from, int fromsz) { @@ -703,6 +728,8 @@ void remove_part(int i) p_info[p] = p_info[p+1]; num_parts--; + if (cur_part == num_parts) + cur_part--; } void insert_empty_part(int i, int first, int last) @@ -751,7 +778,7 @@ void del_part(int i) 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].last_sector = total_size - 1; p_info[i].offset = 0; p_info[i].flags = 0; @@ -781,23 +808,41 @@ void del_part(int i) } int add_part(int num, int id, int flags, int first, int last, int offset, - int want_label) + int want_label, char **errmsg) { 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; /* bad start or end */ + if (num_parts == MAXIMUM_PARTS) { + *errmsg = _("Too many partitions"); + return -1; } - for (i = 0; i < num_parts; i++) + if (first < 0) { + *errmsg = _("Partition begins before sector 0"); + return -1; + } + + if (last < 0) { + *errmsg = _("Partition ends before sector 0"); + return -1; + } + + if (first >= total_size) { + *errmsg = _("Partition begins after end-of-disk"); + return -1; + } + + if (last >= total_size) { + *errmsg = _("Partition ends after end-of-disk"); + 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 (is_extended(ext_info.id) && log > 0) pri++; @@ -810,8 +855,18 @@ int add_part(int num, int id, int flags, int first, int last, int offset, for (i = 0; i < num_parts && p_info[i].last_sector < first; i++); - if (i == num_parts || p_info[i].id != FREE_SPACE - || last > p_info[i].last_sector) { + if (i < num_parts && p_info[i].id != FREE_SPACE) { + if (last < p_info[i].first_sector) + *errmsg = _("logical partitions not in disk order"); + else if (first + offset <= p_info[i].last_sector && + p_info[i].first_sector + p_info[i].offset <= last) + *errmsg = _("logical partitions overlap"); + else + *errmsg = _("enlarged logical partitions overlap"); + return -1; + } + + if (i == num_parts || last > p_info[i].last_sector) { return -1; } @@ -837,8 +892,8 @@ int add_part(int num, int id, int flags, int first, int last, int offset, if (IS_LOGICAL(num)) { if (!is_extended(ext_info.id)) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); + 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 @@ -848,7 +903,7 @@ int add_part(int num, int id, int flags, int first, int last, int offset, */ if (first < ext_info.first_sector) { if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); + print_warning(_("Cannot create logical drive here -- would create two extended partitions")); return -1; } else { if (first == 0) { @@ -860,7 +915,7 @@ int add_part(int num, int id, int flags, int first, int last, int offset, } } else if (last > ext_info.last_sector) { if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); + print_warning(_("Cannot create logical drive here -- would create two extended partitions")); return -1; } else { ext_info.last_sector = last; @@ -976,36 +1031,57 @@ int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, char *available, int menuType, int current ) { int i, lmargin = x, ymargin = y; + char *mcd; + /* Print available buttons */ move( y, x ); clrtoeol(); + for( i = 0; menuItems[i].key; i++ ) { char buff[20]; int lenName; + const char *mi; + /* Search next available button */ while( menuItems[i].key && !strchr(available, menuItems[i].key) ) { 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( current < i && menuItems[current].key < 0 ) current = i; + /* If current item is selected, highlight it */ if( current == i ) /*attron( A_REVERSE )*/ standout (); + /* Print item */ - lenName = strlen( menuItems[i].name ); - if(lenName > itemLength) - print_warning("Menu item too long. Menu may look odd."); + /* Because of a bug in gettext() we must not translate empty strings */ + if (menuItems[i].name[0]) + mi = _(menuItems[i].name); + else + mi = ""; + lenName = strlen( mi ); +#if 0 + if(lenName > itemLength || lenName >= sizeof(buff)) + print_warning(_("Menu item too long. Menu may look odd.")); +#endif + if (lenName >= sizeof(buff)) { /* truncate ridiculously long string */ + strncpy( buff, mi, sizeof(buff)-1); + buff[sizeof(buff)-1] = 0; + } else if( menuType & MENU_BUTTON ) sprintf( buff, "[%*s%-*s]", (itemLength - lenName) / 2, "", - (itemLength - lenName + 1) / 2 + lenName, menuItems[i].name ); + (itemLength - lenName + 1) / 2 + lenName, mi ); else sprintf( buff, "%*s%-*s", (itemLength - lenName) / 2, "", - (itemLength - lenName + 1) / 2 + lenName, menuItems[i].name ); + (itemLength - lenName + 1) / 2 + lenName, mi ); mvaddstr( y, x, buff ); + /* Lowlight after selected item */ if( current == i ) /*attroff( A_REVERSE )*/ standend (); + /* Calculate position for the next item */ if( menuType & MENU_VERT ) { @@ -1028,30 +1104,34 @@ int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, } } } + /* Print the description of selected item */ - mvaddstr( WARNING_START + 1, - (COLUMNS - strlen( menuItems[current].desc )) / 2, - menuItems[current].desc ); + mcd = _(menuItems[current].desc); + mvaddstr( WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd ); return y; } -/* This function takes a list of menu items, lets the user choose one of them * - * and returns the value keyboard shortcut of the selected menu item */ +/* This function takes a list of menu items, lets the user choose one * + * and returns the value keyboard shortcut of the selected menu item */ -int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char *available, int menuType, int menuDefault ) +int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, + char *available, int menuType, int menuDefault ) { int i, ylast = y, key = 0, current = menuDefault; + if( !( menuType & ( MENU_HORIZ | MENU_VERT ) ) ) { - print_warning("Menu without direction. Defaulting horizontal."); + print_warning(_("Menu without direction. Defaulting horizontal.")); menuType |= MENU_HORIZ; } + /* Make sure that the current is one of the available items */ while( !strchr(available, menuItems[current].key) ) { current ++ ; if( !menuItems[current].key ) current = 0; } + /* Repeat until allowable choice has been made */ while( !key ) { @@ -1087,67 +1167,80 @@ int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char * switch( getch() ) { case 'A': /* Up arrow */ - if( menuType & MENU_VERT ) - { - do { - current -- ; - if( current < 0 ) while( menuItems[current+1].key ) current ++ ; - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_UP; + key = MENU_UP; break; case 'B': /* Down arrow */ - if( menuType & MENU_VERT ) - { - do { - current ++ ; - if( !menuItems[current].key ) current = 0 ; - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_DOWN; + key = MENU_DOWN; break; case 'C': /* Right arrow */ - if( menuType & MENU_HORIZ ) - { - do { - current ++ ; - if( !menuItems[current].key ) - { - current = 0 ; - } - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_RIGHT; + key = MENU_RIGHT; break; case 'D': /* Left arrow */ - if( menuType & MENU_HORIZ ) - { - do { - current -- ; - if( current < 0 ) - { - while( menuItems[current + 1].key ) current ++ ; - } - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_LEFT; + key = MENU_LEFT; break; } } } + /* Enter equals to the keyboard shortcut of current menu item */ - if( key == 13 ) - { + if( key == CR) key = menuItems[current].key; - } + + /* Give alternatives for arrow keys in case the window manager + swallows these */ + if ( key == TAB ) + key = MENU_RIGHT; + if ( key == UPKEY ) /* ^P */ + key = MENU_UP; + if ( key == DOWNKEY ) /* ^N */ + key = MENU_DOWN; + + if (key == MENU_UP) { + if( menuType & MENU_VERT ) { + do { + current -- ; + if( current < 0 ) + while( menuItems[current+1].key ) + current ++ ; + } while( !strchr( available, menuItems[current].key )); + key = 0; + } + } + + if (key == MENU_DOWN) { + if( menuType & MENU_VERT ) { + do { + current ++ ; + if( !menuItems[current].key ) current = 0 ; + } while( !strchr( available, menuItems[current].key )); + key = 0; + } + } + + if (key == MENU_RIGHT) { + if( menuType & MENU_HORIZ ) { + do { + current ++ ; + if( !menuItems[current].key ) + current = 0 ; + } while( !strchr( available, menuItems[current].key )); + key = 0; + } + } + + if (key == MENU_LEFT) { + if( menuType & MENU_HORIZ ) { + do { + current -- ; + if( current < 0 ) { + while( menuItems[current + 1].key ) + current ++ ; + } + } while( !strchr( available, menuItems[current].key )); + key = 0; + } + } + /* Should all keys to be accepted? */ if( key && (menuType & MENU_ACCEPT_OTHERS) ) break; /* Is pressed key among acceptable ones */ @@ -1158,7 +1251,7 @@ int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char * { key = 0; putchar( BELL ); - print_warning("Illegal key"); + print_warning(_("Illegal key")); } } /* Clear out prompts and such */ @@ -1181,7 +1274,7 @@ void menuContinue(void) { static struct MenuItem menuContinueBtn[]= { - { 'c', "", "Press a key to continue" }, + { 'c', "", N_("Press a key to continue") }, { 0, NULL, NULL } }; @@ -1196,9 +1289,10 @@ int menuSimple(struct MenuItem *menuItems, int menuDefault) { int i, j, itemLength = 0; char available[MENU_MAX_ITEMS]; + for(i = 0; menuItems[i].key; i++) { - j = strlen( menuItems[i].name ); + j = strlen( _(menuItems[i].name) ); if( j > itemLength ) itemLength = j; available[i] = menuItems[i].key; } @@ -1221,13 +1315,15 @@ void new_part(int i) int num = -1; int num_sects = last - first + 1; int len, ext, j; + char *errmsg; + if (p_info[i].num == PRI_OR_LOG) { static struct MenuItem menuPartType[]= { - { 'p', "Primary", "Create a new primary partition" }, - { 'l', "Logical", "Create a new logical partition" }, - { ESC, "Cancel", "Don't create a partition" }, + { 'p', N_("Primary"), N_("Create a new primary partition") }, + { 'l', N_("Logical"), N_("Create a new logical partition") }, + { ESC, N_("Cancel"), N_("Don't create a partition") }, { 0, NULL, NULL } }; @@ -1243,28 +1339,30 @@ void new_part(int i) else if (p_info[i].num == LOGICAL) num = find_logical(i); else - print_warning("!!! Internal error !!!"); + print_warning(_("!!! Internal error !!!")); - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); + sprintf(def, "%.2f", ceiling(num_sects/(K*0.02))/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))) +#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/cylinder_size)) 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; + num_sects = num_cyls(atof(response)*K)*cylinder_size; } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; + num_sects = num_cyls(atof(response)*K*K)*cylinder_size; + } else if (toupper(response[j]) == 'G') { + num_sects = num_cyls(atof(response)*K*K*K)*cylinder_size; } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; + num_sects = round_int(atof(response))*cylinder_size; } else if (toupper(response[j]) == 'S') { num_sects = round_int(atof(response)); } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; + num_sects = num_cyls(atof(response)*K*K)*cylinder_size; } } @@ -1278,9 +1376,9 @@ void new_part(int i) */ static struct MenuItem menuPlace[]= { - { 'b', "Beginning", "Add partition at beginning of free space" }, - { 'e', "End", "Add partition at end of free space" }, - { ESC, "Cancel", "Don't create a partition" }, + { 'b', N_("Beginning"), N_("Add partition at beginning of free space") }, + { 'e', N_("End"), N_("Add partition at end of free space") }, + { ESC, N_("Cancel"), N_("Don't create a partition") }, { 0, NULL, NULL } }; c = menuSimple( menuPlace, 0 ); @@ -1297,11 +1395,11 @@ void new_part(int i) * extended partition first. */ if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); + print_warning(_("No room to create the extended partition")); return; } (void) add_part(ext, DOS_EXTENDED, 0, first, last, - (first == 0 ? sectors : 0), 0); + (first == 0 ? sectors : 0), 0, &errmsg); first = ext_info.first_sector + ext_info.offset; } @@ -1312,14 +1410,76 @@ void new_part(int i) if (first == 0 || IS_LOGICAL(num)) offset = sectors; - (void) add_part(num, id, flags, first, last, offset, 0); + (void) add_part(num, id, flags, first, last, offset, 0, &errmsg); +} + +void get_kernel_geometry(void) +{ +#ifdef HDIO_GETGEO + struct hd_geometry geometry; + + if (!ioctl(fd, HDIO_GETGEO, &geometry)) { + kern_heads = geometry.heads; + kern_sectors = geometry.sectors; + } +#endif +} + +void get_partition_table_geometry(partition_table *bufp) +{ + struct partition *p; + int i,h,s,hh,ss; + int first = TRUE; + int bad = FALSE; + + if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 || + bufp->p.magicflag[1] != PART_TABLE_FLAG1) + fatal(_("Bad signature on partition table"), 3); + + hh = ss = 0; + for (i=0; i<4; i++) { + p = &(bufp->p.part[i]); + if (p->sys_ind != 0) { + h = p->end_head + 1; + s = (p->end_sector & 077); + if (first) { + hh = h; + ss = s; + first = FALSE; + } else if (hh != h || ss != s) + bad = TRUE; + } + } + + if (!first && !bad) { + pt_heads = hh; + pt_sectors = ss; + } +} + +void decide_on_geometry(void) +{ + heads = (user_heads ? user_heads : + pt_heads ? pt_heads : + kern_heads ? kern_heads : 255); + sectors = (user_sectors ? user_sectors : + pt_sectors ? pt_sectors : + kern_sectors ? kern_sectors : 63); + cylinder_size = heads*sectors; + cylinders = actual_size/cylinder_size; + if (user_cylinders > 0 && user_cylinders <= 0x7fffffff/cylinder_size) + cylinders = user_cylinders; + + total_size = cylinder_size*cylinders; + if (total_size > actual_size) + print_warning(_("You specified more cylinders than fit on disk")); } 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].last_sector = total_size - 1; p_info[0].offset = 0; p_info[0].flags = 0; p_info[0].id = FREE_SPACE; @@ -1337,15 +1497,14 @@ void fill_p_info(void) { 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, 2); + fatal(_("Cannot open disk drive"), 2); opentype = O_RDONLY; - print_warning(READONLY_WARN); + print_warning(_("Opened disk read-only - you have no permission to write")); if (curses_started) { refresh(); getch(); @@ -1365,23 +1524,23 @@ void fill_p_info(void) ioctl(fd, BLKFLSBUF); /* ignore errors */ /* e.g. Permission Denied */ - 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, 3); /* probably a file or cdrom */ + if (ioctl(fd, BLKGETSIZE, &actual_size)) + fatal(_("Cannot get disk size"), 3); read_sector(buffer.c.b, 0); + get_kernel_geometry(); + + if (!zero_table || use_partition_table_geometry) + get_partition_table_geometry(& buffer); + + decide_on_geometry(); + clear_p_info(); if (!zero_table) { + char *errmsg = ""; + for (i = 0; i < 4; i++) { p = & buffer.p.part[i]; bs = get_start_sect(p); @@ -1389,11 +1548,13 @@ void fill_p_info(void) if (p->sys_ind > 0 && add_part(i, p->sys_ind, p->boot_ind, - ((bs <= sectors) ? 0 : bs), - bs + bsz - 1, - ((bs <= sectors) ? bs : 0), - 1)) { - fatal(BAD_PRIMARY, 4); + ((bs <= sectors) ? 0 : bs), bs + bsz - 1, + ((bs <= sectors) ? bs : 0), 1, &errmsg)) { + /* avoid snprintf - it does not exist on ancient systems */ + char *bad = _("Bad primary partition"); + char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30); + sprintf(msg, "%s %d: %s", bad, i, errmsg); + fatal(msg, 4); } if (is_extended(buffer.p.part[i].sys_ind)) tmp_ext = ext_info; @@ -1419,8 +1580,13 @@ void fill_p_info(void) if (add_part(i++, p->sys_ind, p->boot_ind, logical_sectors[logical-1], logical_sectors[logical-1] + bs + bsz - 1, - bs, 1)) - fatal(BAD_LOGICAL, 4); + bs, 1, &errmsg)) { + /* avoid snprintf */ + char *bad = _("Bad logical partition"); + char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30); + sprintf(msg, "%s %d: %s", bad, i-1, errmsg); + fatal(msg, 4); + } } for (pn = 0; @@ -1440,21 +1606,18 @@ void fill_p_info(void) void fill_part_table(struct partition *p, partition_info *pi) { - int sects; + int begin; p->boot_ind = pi->flags; p->sys_ind = pi->id; + begin = pi->first_sector + pi->offset; if (IS_LOGICAL(pi->num)) set_start_sect(p,pi->offset); else - 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); - 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); + set_start_sect(p,begin); + set_nr_sects(p, pi->last_sector - begin + 1); + set_hsc_begin(p, begin); + set_hsc_end(p, pi->last_sector); } void fill_primary_table(partition_table *buffer) @@ -1479,7 +1642,7 @@ void fill_primary_table(partition_table *buffer) void fill_logical_table(partition_table *buffer, partition_info *pi) { struct partition *p; - int i, sects; + int i; for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); if (i == logical || buffer->p.magicflag[0] != PART_TABLE_FLAG0 @@ -1505,12 +1668,8 @@ void fill_logical_table(partition_table *buffer, partition_info *pi) p->sys_ind = DOS_EXTENDED; 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); - 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); + set_hsc_begin(p, pi->first_sector); + set_hsc_end(p, pi->last_sector); } buffer->p.magicflag[0] = PART_TABLE_FLAG0; @@ -1526,7 +1685,7 @@ void write_part_table(void) char response[LINE_LENGTH]; if (opentype == O_RDONLY) { - print_warning(READONLY_WARN); + print_warning(_("Opened disk read-only - you have no permission to write")); refresh(); getch(); clear_warning(); @@ -1538,32 +1697,27 @@ void write_part_table(void) is_bdev = 1; if (is_bdev) { - print_warning(WRITE_WARN); + print_warning(_("Warning!! This may destroy data on your disk!")); while (!done) { mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table " - "to disk? (yes or no): "); + _("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); + else if (strcasecmp(response, _("no")) == 0) { + print_warning(_("Did not write partition table to disk")); return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') + } else if (strcasecmp(response, _("yes")) == 0) done = TRUE; else - print_warning(YES_NO); + print_warning(_("Please enter `yes' or `no'")); } clear_warning(); - print_warning(WRITING_PART); + print_warning(_("Writing partition table to disk...")); refresh(); } @@ -1588,11 +1742,11 @@ void write_part_table(void) clear_warning(); if (changed) - print_warning(YES_WRITE); + print_warning(_("Wrote partition table to disk")); else - print_warning(RRPART_FAILED); + print_warning(_("Wrote partition table, but re-read table failed. Reboot to update table.")); } else - print_warning(YES_WRITE); + print_warning(_("Wrote partition table to disk")); /* Check: unique bootable primary partition? */ ct = 0; @@ -1600,7 +1754,7 @@ void write_part_table(void) if (IS_PRIMARY(i) && p_info[i].flags == ACTIVE_FLAG) ct++; if (ct != 1) - print_warning(NOT_DOS_MBR_BOOTABLE); + print_warning(_("Not precisely one primary partition is bootable. DOS MBR cannot boot this.")); } void fp_printf(FILE *fp, char *format, ...) @@ -1658,7 +1812,7 @@ void print_raw_table(void) to_file = TRUE; } else { mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); + _("Enter filename or press RETURN to display on screen: ")); if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) return; @@ -1666,7 +1820,7 @@ void print_raw_table(void) if (to_file) { if ((fp = fopen(fname, "w")) == NULL) { char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); + sprintf(errstr, _("Cannot open file '%s'"), fname); print_warning(errstr); return; } @@ -1677,16 +1831,16 @@ void print_raw_table(void) } } - fp_printf(fp, "Disk Drive: %s\n", disk_device); + fp_printf(fp, _("Disk Drive: %s\n"), disk_device); - fp_printf(fp, "Sector 0:\n"); + fp_printf(fp, _("Sector 0:\n")); 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)) { - fp_printf(fp, "Sector %d:\n", p_info[i].first_sector); + fp_printf(fp, _("Sector %d:\n"), p_info[i].first_sector); read_sector(buffer.c.b, p_info[i].first_sector); fill_logical_table(&buffer, &(p_info[i])); print_file_buffer(fp, buffer.c.b); @@ -1706,27 +1860,27 @@ void print_p_info_entry(FILE *fp, partition_info *p) char part_str[40]; if (p->id == UNUSABLE) - fp_printf(fp, " None "); + fp_printf(fp, _(" None ")); else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); + fp_printf(fp, _(" Pri/Log")); else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); + fp_printf(fp, _(" Primary")); else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); + fp_printf(fp, _(" Logical")); else fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); + IS_LOGICAL(p->num) ? _("Logical") : _("Primary")); fp_printf(fp, " "); fp_printf(fp, "%8d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? + ((p->first_sector/cylinder_size) != + ((float)p->first_sector/cylinder_size) ? '*' : ' ')); fp_printf(fp, "%8d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? + (((p->last_sector+1)/cylinder_size) != + ((float)(p->last_sector+1)/cylinder_size) ? '*' : ' ')); fp_printf(fp, "%7d%c", p->offset, @@ -1738,29 +1892,29 @@ void print_p_info_entry(FILE *fp, partition_info *p) size = p->last_sector - p->first_sector + 1; fp_printf(fp, "%8d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? + ((size/cylinder_size) != ((float)size/cylinder_size) ? '*' : ' ')); fp_printf(fp, " "); if (p->id == UNUSABLE) - sprintf(part_str, "%.17s", "Unusable"); + sprintf(part_str, "%.17s", _("Unusable")); else if (p->id == FREE_SPACE) - sprintf(part_str, "%.17s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.17s (%02X)", partition_type[p->id], p->id); + sprintf(part_str, "%.17s", _("Free Space")); + else if (partition_type_name(p->id)) + sprintf(part_str, "%.17s (%02X)", partition_type_name(p->id), p->id); else - sprintf(part_str, "%.17s (%02X)", "Unknown", p->id); + sprintf(part_str, "%.17s (%02X)", _("Unknown"), p->id); fp_printf(fp, "%-22.22s", part_str); fp_printf(fp, " "); if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); + fp_printf(fp, _("Boot (%02X)"), p->flags); else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); + fp_printf(fp, _("Unknown (%02X)"), p->flags); else - fp_printf(fp, "None (%02X)", p->flags); + fp_printf(fp, _("None (%02X)"), p->flags); fp_printf(fp, "\n"); } @@ -1776,7 +1930,7 @@ void print_p_info(void) to_file = TRUE; } else { mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); + _("Enter filename or press RETURN to display on screen: ")); if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) return; @@ -1784,7 +1938,7 @@ void print_p_info(void) if (to_file) { if ((fp = fopen(fname, "w")) == NULL) { char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); + sprintf(errstr, _("Cannot open file '%s'"), fname); print_warning(errstr); return; } @@ -1795,11 +1949,11 @@ void print_p_info(void) } } - fp_printf(fp, "Partition Table for %s\n", disk_device); + 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"); + 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)) { @@ -1820,10 +1974,13 @@ void print_p_info(void) 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; + unsigned char ss, es, sh, eh; + int sc, ec; int flags = 0, id = 0; + ss = sh = es = eh = 0; + sc = ec = 0; + if (pi != NULL) { flags = pi->flags; id = pi->id; @@ -1836,20 +1993,9 @@ void print_part_entry(FILE *fp, int num, partition_info *pi) 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; + set_hsc0(&sh, &ss, &sc, start); + set_hsc0(&eh, &es, &ec, end); } fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %8d %9d\n", @@ -1868,7 +2014,7 @@ void print_part_table(void) to_file = TRUE; } else { mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); + _("Enter filename or press RETURN to display on screen: ")); if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) return; @@ -1876,7 +2022,7 @@ void print_part_table(void) if (to_file) { if ((fp = fopen(fname, "w")) == NULL) { char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); + sprintf(errstr, _("Cannot open file '%s'"), fname); print_warning(errstr); return; } @@ -1887,11 +2033,11 @@ void print_part_table(void) } } - fp_printf(fp, "Partition Table for %s\n", disk_device); + fp_printf(fp, _("Partition Table for %s\n"), disk_device); fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number of\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- -------- ---------\n"); + fp_printf(fp, _(" ---Starting--- ----Ending---- Start Number of\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; @@ -1924,10 +2070,10 @@ void print_tables(void) static struct MenuItem menuFormat[]= { - { 'r', "Raw", "Print the table using raw data format" }, - { 's', "Sectors", "Print the table ordered by sectors" }, - { 't', "Table", "Just print the partition table" }, - { ESC, "Cancel", "Don't print the table" }, + { 'r', N_("Raw"), N_("Print the table using raw data format") }, + { 's', N_("Sectors"), N_("Print the table ordered by sectors") }, + { 't', N_("Table"), N_("Just print the partition table") }, + { ESC, N_("Cancel"), N_("Don't print the table") }, { 0, NULL, NULL } }; @@ -1952,51 +2098,50 @@ void print_tables(void) } #define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" void display_help() { char *help_text[] = { - "Help Screen for cfdisk " VERSION, + N_("Help Screen for cfdisk"), "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", + N_("This is cfdisk, a curses based disk partitioning program, which"), + N_("allows you to create, delete and modify partitions on your hard"), + N_("disk drive."), "", - "Copyright (C) 1994-1998 Kevin E. Martin & aeb", + N_("Copyright (C) 1994-1999 Kevin E. Martin & aeb"), "", - "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", + N_("Command Meaning"), + N_("------- -------"), + N_(" b Toggle bootable flag of the current partition"), + N_(" d Delete the current partition"), + N_(" g Change cylinders, heads, sectors-per-track parameters"), + N_(" WARNING: This option should only be used by people who"), + N_(" know what they are doing."), + N_(" h Print this screen"), + N_(" m Maximize disk usage of the current partition"), + N_(" Note: This may make the partition incompatible with"), + N_(" DOS, OS/2, ..."), + N_(" n Create new partition from free space"), + N_(" p Print partition table to the screen or to a file"), + N_(" There are several different formats for the partition"), + N_(" that you can choose from:"), + N_(" r - Raw data (exactly what would be written to disk)"), + N_(" s - Table ordered by sectors"), + N_(" t - Table in raw format"), + N_(" q Quit program without writing partition table"), + N_(" t Change the filesystem type"), + N_(" u Change units of the partition size display"), + N_(" Rotates through MB, sectors and cylinders"), + N_(" W Write partition table to disk (must enter upper case W)"), + N_(" Since this might destroy data on the disk, you must"), + N_(" either confirm or deny the write by entering `yes' or"), + N_(" `no'"), + N_("Up Arrow Move cursor to the previous partition"), + N_("Down Arrow Move cursor to the next partition"), + N_("CTRL-L Redraws the screen"), + N_(" ? Print this screen"), "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", + N_("Note: All of the commands can be entered with either upper or lower"), + N_("case letters (except for Writes)."), END_OF_HELP }; @@ -2005,15 +2150,13 @@ void display_help() erase(); move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - menuContinue(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - + while (strcmp(help_text[cur_line], END_OF_HELP)) { + if (help_text[cur_line][0]) + fp_printf(fp, "%s\n", _(help_text[cur_line])); + else + fp_printf(fp, "\n"); + cur_line++; + } menuContinue(); } @@ -2023,15 +2166,15 @@ int change_geometry(void) int done = FALSE; char def[LINE_LENGTH]; char response[LINE_LENGTH]; - int tmp_val; + int tmp_val, max_cyls, i; while (!done) { static struct MenuItem menuGeometry[]= { - { 'c', "Cylinders", "Change cylinder geometry" }, - { 'h', "Heads", "Change head geometry" }, - { 's', "Sectors", "Change sector geometry" }, - { 'd', "Done", "Done with changing geometry" }, + { 'c', N_("Cylinders"), N_("Change cylinder geometry") }, + { 'h', N_("Heads"), N_("Change head geometry") }, + { 's', N_("Sectors"), N_("Change sector geometry") }, + { 'd', N_("Done"), N_("Done with changing geometry") }, { 0, NULL, NULL } }; move(COMMAND_LINE_Y, COMMAND_LINE_X); @@ -2042,42 +2185,47 @@ int change_geometry(void) switch (toupper( menuSimple(menuGeometry, 3) )) { case 'C': - sprintf(def, "%d", cylinders); + sprintf(def, "%ld", actual_size/cylinder_size); mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { + _("Enter the number of cylinders: ")); + i = get_string(response, LINE_LENGTH, def); + if (i == GS_DEFAULT) { + user_cylinders = actual_size/cylinder_size; + ret_val = TRUE; + } else if (i > 0) { tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; + max_cyls = 0x7fffffff / cylinder_size; + if (tmp_val > 0 && tmp_val <= max_cyls) { + user_cylinders = tmp_val; ret_val = TRUE; } else - print_warning(BAD_CYLINDERS); + print_warning(_("Illegal cylinders value")); } break; case 'H': sprintf(def, "%d", heads); mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); + _("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; + user_heads = tmp_val; ret_val = TRUE; } else - print_warning(BAD_HEADS); + print_warning(_("Illegal heads value")); } break; case 'S': sprintf(def, "%d", sectors); mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); + _("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; + user_sectors = tmp_val; ret_val = TRUE; } else - print_warning(BAD_SECTORS); + print_warning(_("Illegal sectors value")); } break; case ESC: @@ -2088,10 +2236,17 @@ int change_geometry(void) putchar(BELL); break; } + + if (ret_val) { + decide_on_geometry(); + draw_screen(); + } } if (ret_val) { - int disk_end = heads*sectors*cylinders-1; + int disk_end; + + disk_end = total_size-1; if (p_info[num_parts-1].last_sector > disk_end) { while (p_info[num_parts-1].first_sector > disk_end) { @@ -2130,34 +2285,50 @@ void change_id(int i) int num_types = 0; int num_across, num_down; int len, new_id = ((p_info[i].id == LINUX) ? LINUX_SWAP : LINUX); - int y_start, y_end; - int j, pos; + int y_start, y_end, row, row_min, row_max, row_offset, j, needmore; - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; + for (j = 1; i386_sys_types[j].name; j++) ; + num_types = j-1; /* do not count the Empty type */ 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(); + if (y_start < 1) { + y_start = 1; + y_end = COMMAND_LINE_Y - 2; + } else { + 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 (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++; + row_min = 1; + row_max = COMMAND_LINE_Y - 2; + row_offset = 0; + do { + for (j = y_start - 1; j <= y_end + 1; j++) { + move(j, 0); + clrtoeol(); } + needmore = 0; + for (j = 1; i386_sys_types[j].name; j++) { + row = y_start + (j-1) % num_down - row_offset; + if (row >= row_min && row <= row_max) { + move(row, ((j-1)/num_down)*COL_ID_WIDTH + 1); + printw("%02X %-20.20s", + i386_sys_types[j].type, + i386_sys_types[j].name); + } + if (row > row_max) + needmore = 1; + } + if (needmore) + menuContinue(); + row_offset += (row_max - row_min + 1); + } while(needmore); sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); + mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, _("Enter filesystem type: ")); if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) return; @@ -2175,9 +2346,9 @@ void change_id(int i) } if (new_id == 0) - print_warning(ID_EMPTY); + print_warning(_("Cannot change FS Type to empty")); else if (is_extended(new_id)) - print_warning(ID_EXT); + print_warning(_("Cannot change FS Type to extended")); else p_info[i].id = new_id; } @@ -2187,6 +2358,7 @@ void draw_partition(int i) int size, j; int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; char *t; + double fsize; if (!arrow_cursor) { move(y, 0); @@ -2199,38 +2371,38 @@ void draw_partition(int i) "%s%d", my_basename(disk_device), p_info[i].num+1); if (p_info[i].flags) { if (p_info[i].flags == ACTIVE_FLAG) - mvaddstr(y, FLAGS_START, "Boot"); + mvaddstr(y, FLAGS_START, _("Boot")); else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); + 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"); + addstr(_(", NC")); } else { if (p_info[i].offset != 0) - addstr(", NC"); + 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"); + mvaddstr(y, FLAGS_START, _("NC")); } else { if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); + 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")))))); + (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"))))))); t = partition_type_text(i); if (t) mvaddstr(y, FSTYPE_START, t); else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); + mvprintw(y, FSTYPE_START, _("Unknown (%02X)"), p_info[i].id); if (p_info[i].volume_label[0]) { int l = strlen(p_info[i].volume_label); @@ -2240,15 +2412,17 @@ void draw_partition(int i) } size = p_info[i].last_sector - p_info[i].first_sector + 1; + fsize = (double) size * SECTOR_SIZE; 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, SIZE_START, "%9d", size/cylinder_size); + else if (display_units == MEGABYTES) + mvprintw(y, SIZE_START, "%9.2f", ceiling((100*fsize)/(K*K))/100); + else if (display_units == GIGABYTES) + mvprintw(y, SIZE_START, "%9.2f", ceiling((100*fsize)/(K*K*K))/100); + if (size % cylinder_size != 0 || + p_info[i].first_sector % cylinder_size != 0) mvprintw(y, COLUMNS-1, "*"); } @@ -2279,7 +2453,7 @@ void draw_screen(void) int i; char *line; - line = (char *)malloc((COLS+1)*sizeof(char)); + line = (char *) xmalloc((COLS+1)*sizeof(char)); if (warning_last_time) { for (i = 0; i < COLS; i++) { @@ -2297,23 +2471,28 @@ void draw_screen(void) sprintf(line, "cfdisk %s", VERSION); mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); + 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); + { long long bytes = actual_size*(long long) SECTOR_SIZE; + sprintf(line, _("Size: %lld bytes"), bytes); } mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); + sprintf(line, _("Heads: %d Sectors per Track: %d Cylinders: %d"), + heads, sectors, cylinders); + mvaddstr(HEADER_START+4, (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-1, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - mvaddstr(DISK_TABLE_START, LABEL_START+1, "[Label]"); + mvaddstr(DISK_TABLE_START, NAME_START, _("Name")); + mvaddstr(DISK_TABLE_START, FLAGS_START, _("Flags")); + mvaddstr(DISK_TABLE_START, PTYPE_START-1, _("Part Type")); + mvaddstr(DISK_TABLE_START, FSTYPE_START, _("FS Type")); + mvaddstr(DISK_TABLE_START, LABEL_START+1, _("[Label]")); if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " 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)"); + mvaddstr(DISK_TABLE_START, SIZE_START, _("Cylinders")); + else if (display_units == MEGABYTES) + mvaddstr(DISK_TABLE_START, SIZE_START, _("Size (MB)")); + else if (display_units == GIGABYTES) + mvaddstr(DISK_TABLE_START, SIZE_START, _("Size (GB)")); move(DISK_TABLE_START+1, 1); for (i = 1; i < COLS-1; i++) @@ -2368,17 +2547,17 @@ void do_curses_fdisk(void) static struct MenuItem menuMain[]= { - { 'b', "Bootable", "Toggle bootable flag of the current partition" }, - { 'd', "Delete", "Delete the current partition" }, - { 'g', "Geometry", "Change disk geometry (experts only)" }, - { 'h', "Help", "Print help screen" }, - { 'm', "Maximize", "Maximize disk usage of the current partition (experts only)" }, - { 'n', "New", "Create new partition from free space" }, - { 'p', "Print", "Print partition table to the screen or to a file" }, - { 'q', "Quit", "Quit program without writing partition table" }, - { 't', "Type", "Change the filesystem type (DOS, Linux, OS/2 and so on)" }, - { 'u', "Units", "Change units of the partition size display (MB, sect, cyl)" }, - { 'W', "Write", "Write partition table to disk (this might destroy data)" }, + { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") }, + { 'd', N_("Delete"), N_("Delete the current partition") }, + { 'g', N_("Geometry"), N_("Change disk geometry (experts only)") }, + { 'h', N_("Help"), N_("Print help screen") }, + { 'm', N_("Maximize"), N_("Maximize disk usage of the current partition (experts only)") }, + { 'n', N_("New"), N_("Create new partition from free space") }, + { 'p', N_("Print"), N_("Print partition table to the screen or to a file") }, + { 'q', N_("Quit"), N_("Quit program without writing partition table") }, + { 't', N_("Type"), N_("Change the filesystem type (DOS, Linux, OS/2 and so on)") }, + { 'u', N_("Units"), N_("Change units of the partition size display (MB, sect, cyl)") }, + { 'W', N_("Write"), N_("Write partition table to disk (this might destroy data)") }, { 0, NULL, NULL } }; curses_started = 1; @@ -2424,7 +2603,7 @@ void do_curses_fdisk(void) if (p_info[cur_part].id > 0) p_info[cur_part].flags ^= 0x80; else - print_warning(NO_FLAGS); + print_warning(_("Cannot make this partition bootable")); break; case 'D': case 'd': @@ -2434,7 +2613,7 @@ void do_curses_fdisk(void) cur_part = num_parts - 1; draw_screen(); } else - print_warning(DEL_EMPTY); + print_warning(_("Cannot delete an empty partition")); break; case 'G': case 'g': @@ -2454,9 +2633,9 @@ void do_curses_fdisk(void) } else if (p_info[cur_part].offset != 0) p_info[cur_part].offset = 0; else - print_warning(MAX_UNMAXABLE); + print_warning(_("Cannot maximize this partition")); } else - print_warning(MAX_UNMAXABLE); + print_warning(_("Cannot maximize this partition")); break; case 'N': case 'n': @@ -2464,9 +2643,9 @@ void do_curses_fdisk(void) new_part(cur_part); draw_screen(); } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); + print_warning(_("This partition is unusable")); else - print_warning(ADD_EXISTS); + print_warning(_("This partition is already in use")); break; case 'P': case 'p': @@ -2483,16 +2662,18 @@ void do_curses_fdisk(void) change_id(cur_part); draw_screen(); } else - print_warning(TYPE_EMPTY); + print_warning(_("Cannot change the type of an empty partition")); break; case 'U': case 'u': - if (display_units == MEGABYTES) + if (display_units == GIGABYTES) + display_units = MEGABYTES; + else if (display_units == MEGABYTES) display_units = SECTORS; else if (display_units == SECTORS) display_units = CYLINDERS; else if (display_units == CYLINDERS) - display_units = MEGABYTES; + display_units = MEGABYTES; /* not yet GIGA */ draw_screen(); break; case 'W': @@ -2508,20 +2689,20 @@ void do_curses_fdisk(void) if (!draw_cursor(-1)) command = 0; else - print_warning(NO_MORE_PARTS); + print_warning(_("No more partitions")); break; case MENU_DOWN : /* Down arrow */ if (!draw_cursor(1)) command = 0; else - print_warning(NO_MORE_PARTS); + print_warning(_("No more partitions")); break; case REDRAWKEY: clear(); draw_screen(); break; default: - print_warning(BAD_COMMAND); + print_warning(_("Illegal command")); putchar(BELL); /* CTRL-G */ } } @@ -2531,24 +2712,28 @@ void do_curses_fdisk(void) void copyright(void) { - fprintf(stderr, "Copyright (C) 1994-1997 Kevin E. Martin & aeb\n"); + fprintf(stderr, _("Copyright (C) 1994-1999 Kevin E. Martin & aeb\n")); } void usage(char *prog_name) { - fprintf(stderr, "\nUsage:\n"); - fprintf(stderr, "Print version:\n"); - fprintf(stderr, "\t%s -v\n", prog_name); - fprintf(stderr, "Print partition table:\n"); - fprintf(stderr, "\t%s -P {r|s|t} [options] device\n", prog_name); - fprintf(stderr, "Interactive use:\n"); - fprintf(stderr, "\t%s [options] device\n", prog_name); - fprintf(stderr, " -Options: --a: Use arrow instead of highlighting; --z: Start with a zero partition table, instead of reading the pt from disk; --c C -h H -s S: Override the kernel's idea of the number of cylinders, - the number of heads and the number of sectors/track.\n\n"); + /* Unfortunately, xgettext does not handle multi-line strings */ + /* so, let's use explicit \n's instead */ + fprintf(stderr, _("\n" +"Usage:\n" +"Print version:\n" +" %s -v\n" +"Print partition table:\n" +" %s -P {r|s|t} [options] device\n" +"Interactive use:\n" +" %s [options] device\n" +"\n" +"Options:\n" +"-a: Use arrow instead of highlighting;\n" +"-z: Start with a zero partition table, instead of reading the pt from disk;\n" +"-c C -h H -s S: Override the kernel's idea of the number of cylinders,\n" +" the number of heads and the number of sectors/track.\n\n"), + prog_name, prog_name, prog_name); copyright(); } @@ -2559,31 +2744,36 @@ main(int argc, char **argv) int c; int i, len; - setlocale(LC_CTYPE, ""); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); - while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) + while ((c = getopt(argc, argv, "ac:gh: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); + user_cylinders = cylinders = atoi(optarg); + if (cylinders <= 0) { + fprintf(stderr, "%s: %s\n", argv[0], _("Illegal cylinders value")); exit(1); } break; + case 'g': + use_partition_table_geometry = TRUE; + break; case 'h': - heads = atoi(optarg); + user_heads = heads = atoi(optarg); if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); + fprintf(stderr, "%s: %s\n", argv[0], _("Illegal heads value")); exit(1); } break; case 's': - sectors = atoi(optarg); + user_sectors = sectors = atoi(optarg); if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); + fprintf(stderr, "%s: %s\n", argv[0], _("Illegal sectors value")); exit(1); } break; diff --git a/fdisk/common.h b/fdisk/common.h new file mode 100644 index 00000000..d9fa4e8e --- /dev/null +++ b/fdisk/common.h @@ -0,0 +1,8 @@ +/* common stuff for fdisk, cfdisk, sfdisk */ + +struct systypes { + unsigned char type; + char *name; +}; + +extern struct systypes i386_sys_types[]; diff --git a/fdisk/delpart.c b/fdisk/delpart.c new file mode 100644 index 00000000..8504c022 --- /dev/null +++ b/fdisk/delpart.c @@ -0,0 +1,40 @@ +/* very primitive wrapper around the `delete partition' ioctl */ +#include +#include +#include +#include +#include + +int +main(int argc, char **argv){ + int fd; + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + + if (argc != 3) { + fprintf(stderr, + "usage: %s diskdevice partitionnr\n", + argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDONLY)) < 0) { + perror(argv[1]); + exit(1); + } + p.pno = atoi(argv[2]); + p.start = 0; + p.length = 0; + p.devname[0] = 0; + p.volname[0] = 0; + a.op = BLKPG_DEL_PARTITION; + a.flags = 0; + a.datalen = sizeof(p); + a.data = &p; + + if (ioctl(fd, BLKPG, &a) == -1) { + perror("BLKPG"); + exit(1); + } + + return 0; +} diff --git a/fdisk/doc/CFdisk-Portuguese.html b/fdisk/doc/CFdisk-Portuguese.html new file mode 100644 index 00000000..6b699ee9 --- /dev/null +++ b/fdisk/doc/CFdisk-Portuguese.html @@ -0,0 +1,1704 @@ + + + + + + + CFdisk-Portugues-HOWTO + + + +
CFdisk-Portuguese Copyright (C) 1999 Gleydson +M. da Silva
+ +


+
+
+
+
+
+

+


+
 Gleydson M. da Silva - gleydson@linuxbr.com.br +
Versão: 1.68 +
+
+ +


+
+
+
+

[ Indice ] +
  +

1 - Introdução +ao CFdisk +
  1.1 - O que é uma partição +de disco +
  1.2 - O que é a Tabela de partição +
  1.3 - Introdução ao Particionamento +de Discos +
  1.4 - Identificadores utilizados neste +manual +
  1.5 - Identificação de discos +e partições no Sistema Linux +
  1.6 - Tipos de partições +de disco +
  1.7 - Observações sobre +o formato DOS 6.xx (FAT16) +

2 - Iniciando o programa CFdisk +
  2.1 - Opções de Linha de +comando +
  2.2 - Conhecendo a tela do CFdisk +
  2.3 - Descrição dos comandos +
    2.3.1 - Setas Acima/Abaixo +- Esquerda/Direita +
    2.3.2 - <CTRL>+<l> +
    2.3.3 - Boot +
    2.3.4 - Delete +
    2.3.5 - Geometry +
    2.3.6 - Help +
    2.3.7 - Maximize +
    2.3.8 - New +
    2.3.9 - Print +
    2.3.10 - Quit +
    2.3.11 - Type +
    2.3.12 - Units +
    2.3.13 - Write +

3 - Tipos de partições +compatíveis com o CFdisk +

4 - Direitos do Autor +

5 - Licenças e Garantias +sobre este documento +

6 - Notas sobre marcas registradas +

7 - Agradecimentos +
+


+
  +
  +
+
+
+
+

1-) Introdução ao CFdisk

+ +

    CFdisk é um programa utilizado para fazer +o particionamento de discos, utilizando uma interface em modo texto. +
As grandes características deste programa, além de sua +interface de comunicação com o usuário e a enorme +quantidade de partições que manipula, é a grande facilidade +de utilização, o seu poder de manipulação de +partições e a sua precisão que fazem com que o usuário +tenha mais confiança durante o particionamento de disco. +
    É recomendável a leitura deste texto, +mesmo que tenha uma noção sobre o particionamento de discos, +exceto para os gurus que já conhecem a fundo a forma de trabalho, +em geral, de programas deste tipo, pois o particionamento de disco pode +destruir os seus arquivos e partições já existentes, +se for usado de forma incorreta. +
  O programa CFdisk pode ser utilizado em qualquer sistema operacional +que esteja de acordo com o padrão POSIX (Linux, UNIX, FreeBSD, HPUX, +etc). +

  A versão do CFdisk utilizada nas explicações +deste manual é a 0.8, mas isto não impede que este +manual seja utilizado com versões futuras ou anteriores deste programa. +As características principais do programa CFdisk e as explicações +sobre particionamento, são válidas para quaisquer versões +deste programa. +
  +

   Este documento é distribuído com a itenção +de ser útil ao seu utilizador, no entanto NÃO TEM NENHUMA +GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS OU +DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença +Pública Geral  GNU para maiores detalhes. +

+ +
  +
  +
  +
+

1.1-) Partição de Disco

+ +

    Uma Partição de Disco é +o local onde o sistema operacional armazena seu sistema de arquivos(arquivos, +diretórios, FAT, boot sector, etc). +

+ +
+


1.2-) Tabela de partição

+ +

    A Tabela de partição é +o local do disco rígido onde se localizam os dados sobre todas as +partições existentes no disco como o sistema de arquivos +utilizado, se ela é inicializável, a cabeça inicial/final, +setor inicial/final, cilindro inicial/final, número de setores ocupados +por ela no disco. +
  +

+ +
+


1.3-) Introdução +ao particionamento de discos

+ +

    Particionar o disco rígido é dividir +ele em partes para armazenamento de arquivos e programas. As partições +criadas no disco podem ter o tamanho que desejar (desde que esteja dentro +da capacidade máxima do disco rígido). +
     Uma partição não interfere +em outras partições do mesmo disco(é como se tivessemos +vários discos rígidos dentro de um), e nem em outros discos +rígidos(caso possuir mais que um disco rígido) instalado +em seu computador. +
    Pode ser criada  uma partição +única, que neste caso todo o disco rígido é usado +para armazenar os arquivos(que é o caso mais comum caso voce tenha +o DOS), ou várias partições, que podem ser usadas +pelo mesmo SO(Sistema Operacional) ou outros sistemas operacionais diferentes(um +exemplo de várias partições: se for usar o DOS e o +Linux no mesmo disco, os dois sistemas vão +
estar no mesmo disco mas um não interfere no outro). +
ATENÇÃO : A OPERAÇÃO DE PARTICIONAMENTO +DE DISCOS PODE FAZER +
                     +COM  QUE OS DADOS ARMAZENADOS EM SEU DISCO RÍGIDO SEJAM +
                     +PERDIDOS, SE FOR USADA INCORRETAMENTE. É SEMPRE +
                     +RECOMENDADO RETIRAR UMA CÓPIA DE SEGURANÇA DOS SEUS +
                     +ARQUIVOS EXISTENTES NO MICRO ANTES DE SE EXECUTAR UM +
                     +PROGRAMA DESTE TIPO, A NÃO SER QUE TENHA CONFIANÇA NO +
                     +QUE ESTA FAZENDO E QUE ENTENDEU AS EXPLICAÇÕES SOBRE A +
                      +IDENTIFICAÇÃO DE  DISCOS RÍGIDOS E SUAS PARTIÇÕES +NO +
                      +SISTEMA. +
    Neste manual voce aprenderá como deve particionar +seu disco rígido para a instalação do SO usando o +programa CFdisk. +

+ +
+


1.4-) Algumas identificações +utilizadas neste manual para facilitar a +
compreensão do texto

+ +

    Esta parte descreve algumas características +de organização deste manual e algumas identificações +que utilizei para facilitar o seu entendimento, e as explicações +que serão dadas. +

    Explicação de nomes e comandos, sera +seguida da palavra "onde:" e abaixo dela as explicações +sobre os comandos, exemplo: +

onde: +
nome a ser explicado1  : Descrição +
nome a ser explicado2  : Descrição +
nome a ser explicado3  : Descrição +

ou +

onde: +
nome a ser explicado1  - Descrição +
nome a ser explicado2  - Descrição +
nome a ser explicado3  - Descrição +
  +

    Quando for feita alguma referência com tecla +do teclado, por exemplo, pressione p para listar as partições, +a letra sera colocada entre <> para que seja melhor entendida, por exemplo: +

pressione <d> para deletar uma partição... +
...pressione <Enter> para escolher a opção do menu. +
pressione <t> para listar os tipos de partições disponíveis... +
  +

    As linhas pontilhadas que aparecem na tela, veja +abaixo, +
---------------------------------------------------------------------------- +
---------------------------------------------------------------------------- +
servem para identificar que o que esta entre as linhas é um +exemplo de como +
será a resposta do comando para a tela de seu computador. +

+ +
+


1.5-) Identificação +de discos e partições no Linux

+ +

    Antes de descrever como se utiliza o programa CFdisk, +é importante fazer algumas explicações sobre a identificação +das partições e unidades de disco no sistema Linux( e outros +*nix). +
    Se voce for um usuário que já conhece +a interpretação de discos e partições neste +sistema, voce não precisará ler esta parte. +
    No sistema operacional Linux, os dispositivos existentes +no computador (como impressoras, unidades de disquetes, discos rígidos, +monitor, placa de som, etc...) são identificados por um nome referente +a este dispositivo e colocado no diretório /dev (que é +utilizado para identificar os dispositivos ou periféricos existentes +no computador). +
   A identificação dos discos rígidos +segue a seguinte forma: +

  /dev/hda1 +
  |        |  |  +| +
  |        |  |  +|_Número que identifica a partição do disco rígido(1=Primeira, +2=segunda) +
  |        |  | +
  |        |  |_Letra +que identifica o disco rígido(a=primeiro disco, b=segundo disco, +etc..) +
  |        | +
  |        |_Sigla hd +- Significa que é um disco rígido IDE(Se tiver um +sd +significa SCSI) +
  | +
  |_ Identificação do diretório onde os dispositivos +do sistema são armazenados +

OBS: As unidades de disco rígido SCSI, são +identificadas com as letras sd +
         seguida pela letra +da unidade e número da partição e os discos IDE +são +
         identificados por +hd +seguida pela letra da unidade de disco e o número +
         da partição +do disco(como visto acima). +

Abaixo, algumas identificações de disco do sistema Linux: +

/dev/hda1    -   Disco rígido IDE primário +principal - Primeira partição +
/dev/hda2    -   Disco rígido IDE primário +principal - Segunda partição +
/dev/hda3    -   Disco rígido IDE primário +principal - Terceira partição +
/dev/hdb1    -   Disco rígido IDE primário +escravo - Primeira partição +
/dev/hdb2    -   Disco rígido IDE primário +escravo - Segunda partição +
/dev/hdb3    -   Disco rígido IDE primário +escravo - Terceira partição +
/dev/hdc1    -   Disco rígido IDE secundário +principal - Primeira partição +
/dev/hdc2    -   Disco rígido IDE secundário +principal - Segunda partição +
/dev/hdc3    -   Disco rígido IDE secundário +principal - Terceira partição +
/dev/hdd1    -   Disco rígido IDE secundário +escravo - Primeira partição +
/dev/hdd2    -   Disco rígido IDE secundário +escravo - Segunda partição +
/dev/hdd3    -   Disco rígido IDE secundário +escravo - Terceira partição +
/dev/sda1    -   Primeiro disco rígido +SCSI - Primeira partição +
/dev/sda2    -   Primeiro disco rígido +SCSI - Segunda partição +
/dev/sda3    -   Primeiro disco rígido +SCSI - Terceira partição +
/dev/sdb1    -   Segundo disco rígido +SCSI - Primeira partição +
/dev/sdb2    -   Segundo disco rígido +SCSI - Segunda partição +
/dev/sdb3    -   Segundo disco rígido +SCSI - Terceira partição +

    No exemplo acima foram usadas 3 partições +por disco, mas podem existir mais partições no mesmo disco, +um exemplo é se o disco rígido possuir partições +Lógicas, que são identificadas no sistemas a partir de +/dev/hdx5. +
  +

    Abaixo um exemplo de como o Linux identifica as partições +em cada disco existente em seu computador: +

Vamos supor que eu tenha 2 discos rígidos: +
o 1ºdisco de 2GB e o 2ºdisco  de 1GB(Giga +Byte ou 1.000 Megas!) +

    No primeiro disco(de 2GB), a primeira partição +é de 800MB do tipo FAT16(DOS), a segunda partição +é de 1.2GB do tipo EXT2(Linux)(1.2GB+800MB=2GB que +é a capacidade total do disco). Assim as partições +seriam identificadas da seguinte forma no Linux: +

/dev/hda   - Disco rígido Primário Principal +
/dev/hda1 - Primeira partição do primeiro disco +rígido (de 800MB do tipo DOS) +
/dev/hda2 - Segunda partição do primeiro disco +rígido( de 1.2GB do tipo Linux) +

    Neste caso estariam disponíveis 800MB para +serem usados com o DOS e 1.2GB para o Linux.     Por +exemplo, se voce particionar um disco rígido em duas partes e usar +as duas partições no DOS, ele reconhecerá as partições +como sendo C: e D:. +

Lembre-se: Quando um disco é particionado, nenhuma partição +interfere na outra, repare que +
                    +quando voce particiona(divide) um disco,  é como se tivesse +dois discos rígidos(o +
                    +único cuidado que voce deve tomar é com as cópias +de segurança, porque se der um +
                    +problema de parte eletrônica no disco rígido, por exemplo, +a sua placa controladora +
                    +queimar ou o cabeçote dele ir pro espaço, voce perderá +as suas 2 partições que estão +
                    +armazenadas nele. +
  +

Voltando ao exemplo das classificações das partições +do disco, vamos para o segundo disco: +

    No segundo disco(1GB), eu tenho uma partição +de 950MB do tipo FAT16(DOS), que costumo usar para armazenar +arquivos temporários e cópias de segurança de meu +sistema, etc..., e outra de 50MB SWAP(Partição de +memória virtual como descrevi acima)(950MB+50MB=1GB). Então +as partições deste disco seriam identificadas da seguinte +forma no Linux: +

/dev/hdb   - Disco rígido principal escravo +
/dev/hdb1 - Primeira partição do disco acima ( +de 950MB do tipo DOS) +
/dev/hdb2 - Segunda partição do disco acima ( +de 50MB do tipo SWAP) +

    No disco acima, 950MB estão disponíveis +para serem usados pelo DOS e 50 MB pela memória virtual +(SWAP) do Linux. +

    Note que se voce utiliza o MS-DOS, voce não +conseguirá ver as partições do Linux e SWAP, +porque são imcompatíveis com o formato aceito pelo DOS +(ele identificaria a primeira partição do primeiro disco(800MB) +como a unidade C: e a primeira partição do segundo disco(950MB) +como unidade D), mas o contrário não acontece; O Linux +tem total compatibilidade com a partição +
DOS FAT12, FAT16, FAT32, OS/2 HPFS, e muitas outras. +

+ +
+


1.6-) Tipos de partições +de discos

+ +

   As partições de disco são divididas +em tres tipos: Primária, Extendida e Lógica. +
   Pode se ter, no máximo, 4 partições +Primárias +e Extendidas no mesmo disco (3 Primárias e 1 Extendida ou +4 partições Primárias em cada disco). +
A partição Primária permite o armazenamento +de arquivos e diretórios. Todos os computadores que possuem somente +a unidade C: (supondo que utilize o DOS), utilizam este tipo de +partição para armazenamento de arquivos e inicialização +do sistema operacional. +
    Se for preciso criar mais que 4 partições +no mesmo disco, será necessário criar uma partição +Extendida. +A partição Extendida não pode ser utilizada para armazenar +arquivos. Ela é usada para a criação de outras partições, +dentro dela, que são chamadas de partições Lógicas. +
    Uma partição Extendida podem +conter várias partições Lógicas. As +partições Lógicas podem armazenar arquivos +e diretórios(como as partições primárias). +
    Um mesmo disco rígido pode armazenar mais +de 64 partições independentes uma das outras. +

LEMBRE-SE: Os arquivos e diretórios podem ser armazenados +somente em partições de disco primárias ou lógicas, +a partição extendida não é usada para armazanamento +de arquivos e diretórios. +

   Se possuir duas partições em seu computador +(C: e D: no DOS), e não estiver usando a partição +D:, +a instalação do Linux pode ser feita nesta partição +desde que ela tenha o espaço necessário para o sistema operacional +Linux, os programas que desejar instalar, mais a partição +SWAP.  +

+ +
+


1.7-) Observações +sobre o formato DOS 6.XX(FAT 16)

+ +

     No formato DOS 6.XX(FAT16), o primeiro +setor da área de dados da partição é utilizado +frequentemente pelo DOS para armazenamento de dados sobre a partição +de disco, e estes dados são usados pelo sistema para se ter maior +confiabilidade do que os dados armazenados na tabela de partição. +O sistema de arquivos DOS, faz o FDISK(do DOS) limpar os primeiros 512 +bytes da área de dados da partição sempre que uma +mudança de tamanho acontecer. +
     O formatador do DOS(format) verifica +este primeiro setor toda vez que a upção /U (que é +utilizada para não salvar dados para se fazer a desformatação +do disco) foi utilizada. +
     Isto é considerado uma FALHA no Format(do +DOS) e no Fdisk(do DOS). +

     A opção abaixo deve ser utilizada +caso voce crie uma partição do DOS FAT16 com o CFdisk, que +faz com que os primeiros 512 bytes daquela partição sejam +"limpos", para manter a compatibilidade com o DOS. Utilize esta opção +dentro do Linux, após criar a partição com o CFdisk +e reiniciar o seu computador. Foi notado que esta opção só +funciona corretamente somente quando o Sistema Linux estiver instalado +em seu computador. Não me responsabilizo caso utiliza-la a partir +de um disquete de recuperação. +

dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 +

onde: +
hdx1 - É a identificação da unidade de +disco e a partição que foi criada  pelo CFdisk utilizando +o +
           sistema +de arquivos DOS que terá seu primeiro setor "limpo". +
  +

OBS1: Cuidado ao utilizar esta opção, um pequeno +descuido pode resultar na perda de dados do +
            +seu disco rígido ou outras partição. +
OBS2: Não utilize este comando com partições +que utilizam o sistema de arquivos FAT32(utilizada +
            +nos sistemas operacionais Windows 95 OSR/2 e superiores) .Se esta opção +for utilizada +
            +em um disco utlizando este sistema de arquivos, sua FAT será corrompida, +caso isto +
            +acontecer, será necessária a re-formatação +da partição. +
OBS3: É extremamente recomendado que se utilize o programa +de particionamento que +
           acompanha  +o seu sistema operacional. Por exemplo, se deseja criar  uma partição +DOS +
           6.XX, +utilize o FDisk qua acompanha o DOS. +

+ +
+


2-) Iniciando o programa CFdisk

+ +

    Para entrar no programa CFdisk digite: +

cfdisk <unidade> +

onde: +
unidade - é a unidade de disco que deseja utilizar para +fazer o particionamento. A unidade pode +
               +ser:  /dev/hda, /dev/hdb, /dev/hdc ..., /dev/sda, /dev/sdb...,etc +

NOTA: Se voce não digitar a unidade, o cfdisk utilizará +a unidade /dev/hda como padrão. +

+ +
+


2.1-) Opções de +linha de comando utilizadas com o CFdisk

+ +

  Opções de linha de comando fazem com que o programa +inicie de forma específica ou personalizada. As opções +devem ser digitadas após o nome do programa (cfdisk). +

       cfdisk <unidade> +< -avz > < -c cilindros > < -h cabeçotes +> +
              +< -s  setores_por trilha > < -P opt > < dispositivo +> +

onde: +
-a        Usa um cursor seta +ao invés de video reverso para destacar a +
          partição +atual. +
-v        Mostra a versão +do programa e Coyright(Direitos Reservados). +
-z        Ignora a leitura +da tabela das partições existentes no disco +
          ao iniciar o +CFdisk. +

-c Número de Cilindros do disco +
-h Número de Cabeçotes do disco +
-s Setores por trilha existentes no disco. +
-P OPC    Mostra a tabela de partição +no formato especifico. +
          OPC - +Pode ser: +
                     + +r - Mostra a tabela de partição em Formato RAW +
                     + +s - Mostra a tabela de partição em Format de Setores +
                     + +t -  Mostra a tabela de partição classificada +pelo número da partição +
                          +Para maiores detalhes, veja O comando Print <p>. +

OBS: A utilização dos parâmetros -c -h -s, +substituirão os parâmetros da BIOS da placa, utilize +
          estas opções +se sua bios não utilizar estes parâmetros ou se mostrar valores +incorretos. +

    Após entrar o programa CFdisk, ele verificará +automaticamente o tamanho do Disco Rígido, se não conseguir, +o programa será terminado. +
    Para resolver este problema, especifique o tamanho +do disco em cilindros, cabeças, e setores na linha de comando que +inicia o programa. Este problema geralmente acontece quando se tenta particionar +uma unidade de disco SCSI que esteja conectada a uma placa controladora +que não possui BIOS, e  quando  uma  BIOS  +mostra  os  valores  da  geometria  do  disco(tamanho) +
incorretamente. +
    O próximo passo do CFdisk é fazer +a leitura das partições atuais do disco, se não conseguir, +o programa será terminado. O único motivo para o CFdisk mostrar +esta mensagem de erro, é se voce digitar parâmetros incorretos +para o tamanho do disco, caso tenha acontecido o problema +
descrito no paragrafo anterior. Verifique se os parâmetros foram +digitados incorretamente, se os parâmetros estiverem digitados corretamente +e mesmo assim o programa continua dando erro na leitura das partições, +utilize a opção -z na linha de comando do programa, +que faz com que ele ignore a leitura das partições existentes +no disco ao iniciar . +

+ +
+


2.2-) Conhecendo a Tela do CFdisk

+ +

   Após digitar CFdisk, será mostrada a tela +principal onde voce poderá acionar os comandos para manipulação +das partições de disco, e visualizar as partições +de disco atuais e outros dados. +
Abaixo o exemplo e explicações sobre esta tela. +

O disco utilizado para os exemplos é um disco de 5157 MB +de Capacidade com: +
- 10672 Cilindros  15 Cabeças  63 +Setores (no modo C/H/S) +
- 627 Cilindros   255 Cabeças  +63 Setores (no modo LBA) +
   A unidade de medida utilizada pelo CFdisk para mostrar +os parâmetros do disco será o mesmo configurado na BIOS, ou +seja, se estiver utilizando o disco com o modo de operação +em LBA, os valores de cilindros, cabeças e setores motrados +pelo CFdisk sera em LBA. +
  +

--------------------------------------------------------------------------------------------------- +

CFdisk 0.8l +
Disk Drive: /dev/hda +
Heads:255  Sectores per track:63  Cylinders:627
+--------------------------------------------------------------------------------------------------- +
Name            +Flags             +Part Type        FSType                   +[LABEL]              +Size(MB) +
hda1              +Boot              +Primary     Win 95 FAT 32                                         +1953.12 +
hda5                                    +Logical     DOS FAT 16 (BIG)    GLEYDSON            +172.58 +
                                           +Pri/Log      Free Space                                                +2910.55 +
  +
  +
  +
  +
  +
  +
  +
  +
  +

[Bootable]   [Delete]   [Help]   [Maximize]   +[Print] +
[Quit]          [Type]     +[Units]  [Write] +
---------------------------------------------------------------------------- +
     No cabeçalho da tela, é mostrada +a versão do programa, a unidade de disco que será usada no +particionamento e os parâmetros de tamanho do disco(cabeçotes, +cilindros e setores). +
Abaixo do cabeçalho após a linha pontilhada, se encontra +a área das partições. +

onde: +
- Name  : é o nome da(s) partição(ões) +de Disco. +
- Flags   : Se estiver marcada como BOOT, será +possível iniciar o sistema a partir desta partição +
                +(quando não se utiliza um Boot Manager). Se estiver marcada como +NC (Não +
                +compatível)  significa que esta partição não +é compatível com o DOS, OS/2, etc. Para +
                +maiores detalhes, veja O comando Maximize <m>. +
- Type   : O tipo da partição pode ser +Primária ou Lógica. Para espaço não particionado, +o +
               +tipo da partição pode ser Primário/Log. +
- FileSystems : Tipo de Sistema de Arquivos que é usado +naquela partição. Se o sistema de +
                +arquivos for desconhecido, ele será mostrado como um valor Hexadecimal. +Um +
                +caso especial ocorre quando há Partições do Disco +Rígido que não podem ser +
                +usadas ( porque toda a partição primária esta em uso). +Quando isto é detectado, o +
                +tipo de FileSystems é mostrado como não usável(Unusable) +para criação de novas +
                +partições. +
- Label   : Nome de volume da partição de disco. +Os nomes de partições FAT32,  não são +
                +mostrados com esta versão do CFdisk. +
- Size      : Mostra o tamanho que cada partição +ocupa no disco rígido em  MegaBytes (por +
                 +padrão). +
                +Também pode mostrar o tamanho ocupado por Setores ou Cilindros. +Se for mostrado +
                +um asterisco (*) após o tamanho, isto diz que a partição +não esta alinhada com Cilindro. +

   O espaço livre existente no disco para criação +de novas partições, é mostrado como uma outra partição, +com o FSType(sistema de arquivos) Free Space(espaço Livre). +

OBS: As partições de disco Extendidas não +são mostradas na tela do CFdisk durante o +
          particionamento, +mesmo assim, as partições lógicas que este tipo de +partição armazena, +
          serão +mostradas a partir de hdx5 ou sdx5. +

    No rodapé da tela, encontramos os comandos +utilizados pelo CFdisk para manipular as partições de disco. +Os comandos são mostrados entre Chaves []. +
    Todos os comandos no rodapé da tela, são +aplicaveis somente para a partição que estiver destacada +com a barra(video reverso).  Veja descrições dos comandos +do CFdisk para mais detalhes. +
    Abaixo do rodapé da tela, é mostrada +a descrição do comando que estiver em destaque com o cursor +em video reverso. +

    Veja abaixo a tradução da tela principal +do programa CFdisk: +
--------------------------------------------------------------------------------------------------- +

CFdisk 0.8l +
Unidade de Disco: /dev/hda +
Cabeças:255  Setores por trilha:63  Cilindros:627
+--------------------------------------------------------------------------------------------------- +
Nome        Opções        +Tipo Part.      Tipo Sist. Arquivos       +[VOLUME]        Tamanho(MB) +
hda1           Boot            +Primary           Win +95 FAT 32                                        +1953.12 +
hda5                               +Logical         DOS FAT 16 (BIG)     +GLEYDSON            +172.58 +
                                      +Pri/Log            +Espaço Livre                                             +2910.55 +
  +
  +
  +
  +
  +
  +
  +
  +
  +

[Inicializável]    [Apagar]    +[Ajuda]     [Maximizar]    [Imprimir] +
[Sair]               +[Tipo]        [Unidades][Gravar] +
---------------------------------------------------------------------------- +

+ +
+


2.3-) Descrição +dos comandos do CFdisk

+ +

    Os comandos do programa são utilizados criar +partições, entrar na ajuda do programa, alterar o tipo da +partição, apagar uma partição, etc. +
    Pode ser utilizado Seta p/ Esquerda e Seta p/ direita +para se movimentar entre os comandos, quando o cursor estiver em cima do +comando que deseja executar, pressione <Enter>. +
    Outro método que se pode utilizar para acionar +uma opção do CFdisk, é pressionando a primeira letra +de cada opção, automaticamente a opção é +executada(sem ter que pressionar <Enter>). Neste método, todos +os comandos aceitam letras maiúsculas e minúsculas, exceto +o comando Write(gravar partição) que é executado somente +se pressionar <W> maiúscula, para evitar +
gravações acidentais o disco. +
    Quando estiver em um Sub-Menu e desejar retornar +ao menu principal, pressione a tecla <Esc>.  +

+ +
+


2.3.1-) Setas Acima e Abaixo/ +Esquerda e Direita (Movimentação do Cursor)

+ +

    Setas Acima e Abaixo são utilizadas para se +movimentar entre as partições existentes no disco e espaço +livre, selecionando-a para que seja utilizada as opções do +CFdisk. +
    Setas Esquerda e Direita são utilizadas para +selecionar entre as opções diponíveis do programa(que +serão explicadas abaixo). Para confirmar uma opção, +pressione <Enter>. +

+ +
+


2.3.2-) <CTRL>+<l>

+ +

   Este comando é utilizado para atualizar a tela manualmente +caso a atualização automática falhar, por exemplo, +quando uma partição for excluida, e continuar a ser mostrada +na tela. +

+ +
+


2.3.3-) Boot <b>

+ +

   Este comando permite escolher se a partição +Primária atual será utilizada para iniciar o sistema(BOOT). +Selecione esta opção para selecionar entre partição +inicializável ou não inializável. Quando uma partição +estiver marcada como inicializável, aparecerá a palavra BOOT +na coluna Flags(na tela principal do programa). +

OBS: Não será necessário marcar a partição +Linux como inicializável, caso se esteja utilizando um +
          Boot Manager(como +o LILO) para escolher qual sistema operacional sera utilizado para +
         inicializar o sistema. +

+ +
+


2.3.4-) Delete <d>

+ +

   Este comando apaga a partição selecionada +do disco. Após apagar a partição, o espaço +ocupado por ela é convertido para espaço livre. +
  A partição marcada atualmente como Free Space +ou como Unusable não pode ser apagada. +

+ +
+


2.3.5-) Geometry <g>

+ +

   Este comando não é mostrado no menu, pois +é utilizado para alterar o tamanho (Cilindros, Cabeças e +Setores do disco). Este comando só pode ser acionado se for pressionada +a tecla <g>. +

CUIDADO: Esta opção é recomendada somente +para aqueles que sabem os riscos que o uso +
                     +desta opção pode fazer, e se a situação que +estão, requerem o seu uso. +
   Uma situação que esta opção +é util, é se o BIOS do seu computador não mostrar +corretamente os parâmetros do disco(Cilindros, Cabeçotes ou +Setores), sendo necessário que se passe manualmente o tamanho do +disco para que seja feito o correto particionamento do disco. +

OBS: Caso seu disco rígido for SCSI e placa controladora +dele não tiver BIOS,  provavelmente o +
          CFdisk não +será iniciado. Se este problema ocorrer, digite os parâmetros +do disco na linha +
          de comando ao +iniciar o programa. Para maiores detalhes, veja opções de +linha de comando +
          do CFdisk.. +

Após pressionar <g> será mostrada a seguinte tela: +

---------------------------------------------------------------------------------------------------- +

CFdisk 0.8l +
Disk Drive: /dev/hda +
Heads:255  Sectors:63  Cilinders:627
+---------------------------------------------------------------------------------------------------- +
Name        Flags         +Part Type           File +System              +[LABEL]         Size(MB) +

hda1         Boot           +Primary          Win 95 FAT +32                                   +1953.12 +
hda5                           +Logical        DOS FAT 16 (BIG)     +GLEYDSON        172.58 +
                                   +Pri/Log            +Espaço Livre                                       +2910.55 +
  +
  +
  +
  +
  +
  +
  +
  +

[ Cylinders]  [Heads]  [Sectors]  [Done] +

---------------------------------------------------------------------------- +
onde: +
Cylinders  : Altera o número de Cilindros do disco +atual durante o particionamento. +
Heads       : Altera o número +de Cabeças do disco atual durante o particionamento. +
Sectors     : Altera o número de +Setores do disco atual durante o particionamento. +
Done        : Quando finalizar +as alterações, tecle <d> ou selecione Done para +
                   +que o CFdisk modifique os valores de Cilindros, Cabeças e Setores +
                   +que utiliza para particionar o disco e retorne a tela anterior. +
  +

     Quando escolher algum parâmetro acima +para alteração(Cilindros, cabeçotes ou Setores do +disco), será vista uma tela como esta: +
---------------------------------------------------------------------------------------------------- +

CFdisk 0.8l +
Disk Drive: /dev/hda +
Heads:255  Sectors:63  Cilinders:627
+---------------------------------------------------------------------------------------------------- +
Name          Flags           +Part Type             +File System               +[LABEL]                +Size(MB) +

hda1            +Boot             +Primary            +Win 95 FAT 32                                           +1953.12 +
hda5                                +Logical           DOS +FAT 16 (BIG)     GLEYDSON               +172.58 +
                                        +Pri/Log               +Espaço Livre                                              +2910.55 +
  +
  +
  +
  +
  +
  +
  +
  +

Enter the number of Cylinders: 627 +

---------------------------------------------------------------------------- +
     O valor que aparece ao selecionar a opção, +é o valor que o disco esta utilizando atualmente (cilindros), +e será pedido que digite um valor para os Cilindros, que substituirá +os da BIOS durante a seção de particionamento.  Para +sair desta tela sem alterar o valor, pressione <ESC>. A mesma tela e +explicação se aplicam para as alterações de +Cabeças e Setores. +

OBS: Se por acaso digitar um valor incorretamente para o tamanho +do disco e     não se lembrar +
          mais do valor +antigo ou original, selecione a opção Done, e  tecle +<q> para sair do CFdisk +
         sem gravar as alterações +feitas para o disco, pois se continuar a utilizar o CFdisk com o +
         tamanho do disco incorreto, +os dados existentes nele e até mesmo partições poderão +ser +
         perdidos(as). +

   Se aumentar o tamanho do disco, setores adicionais são +acrescentados no final do disco, e são mostrados como espaço +livre. +
   Se diminuir o tamanho do disco, as partições +que estavam localizadas após o setor/cilindro que foi excluido(se +existir alguma), será apagada e a última partição(ou +espaço livre ao final do disco rígido), terá seu tamanho +alterado e terminará neste "novo" último setor do disco. +

+ +
+


2.3.6-) Help <h> ou <?>

+ +

    O comando Help mostra a tela de ajuda do programa, +que descreve as funções das teclas utilizadas pelo programa +e suas funções. +

+ +
+


2.3.7-) Maximize <m>

+ +

   Este comando aumenta a utilização de espaço +do disco na partição atual. Isto porque o DOS, OS/2 +e outros sistemas operacionais utilizam o primeiro setor da primeira trilha +da partição do disco e em todas as partições +Lógicas para iniciar o sistema operacional, utilizando a segunda +trilha em diante daquela partição para fazer o armazenamento +de arquivos. Este espaço perdido entre o segundo e o último +Setor da primeira trilha da primeira cabeça, pode ser recuperado +com a utilizando este comando. +
    Este comando faz com que a partição +se torne imcompatível com DOS, OS/2 e outros Sistemas +Operacionais que utilizam este primeiro Setor do disco para iniciar o sistema +operacional. +
   Se este comando for utilizado, será colocada uma +opção chamada NC(não compatível) em +Flags(na tela principal do CFdisk). +
   Esta opção faz o uso máximo do disco +e a incompatibilidade com o DOS/OS/2, etc. O padrão quando +criando uma Partição, é criando Partições +compativeis com o DOS, OS/2, etc. +

OBS: O Fdisk(versão 8 e superiores) e partições +formatadas com o sistema de arquivos FAT32, +
          fazem a utilização +completa deste espaço entre o segundo e o último Setor da  +primeira trilha +
          do disco, eliminando +o desperdício de espaço. +

+ +
+


2.3.8-) New <n>

+ +

   O comando New<n>, cria uma nova partição +usando o espaço livre(FreeSpace) existente no disco. Após +escolher esta opção, o CFdisk perguntará se deseja +criar uma partição Primária, Lógica +ou Cancelar o comando. +
    Escolhendo criar uma partição Primária +ou Lógica, o sistema perguntará o tamanho da partição +que deseja criar, por padrão, o CFdisk mostrará o espaço +livre total disponível no disco para a criação da +nova partição(em MegaBytes). Tecle <Enter> para criar +uma partição do tipo escolhido com este tamanho ou digite +um tamamho menor. O CFdisk permite que seja digitados valores em: +
- MegaBytes(M - o padrão do programa) +
- KiloBytes(K) +
- Cilindros(C) +
- Setores(S) +
Digitando-se o tamanho da partição seguida de uma das +letras acima. Se a letra não for digitada, +
o programa assumirá o tamanho que digitou em MegaBytes. +

OBS1: Quando criar uma partição Lógica, +automaticamente será criada uma partição +
            +Extendida, entre hdx1 e hdx4, e a partição Extendida não +é  mostrada na tela de +
             +particionamento de disco. Se desejar exibir a partição extendida, +execute o comando +
             +PRINT <p> e escolha a opção Sector para verificar +qual é a identificação da partição +
             +Extendida  no disco. Para maiores detalhes, veja o comando +PRINT <p>. +
OBS2: São permitidas, no máximo, 4 partições +Primárias +e Extendidas(3 Primárias e 1 +
            +Extendida ou 4 partições Primárias em cada +disco). O CFdisk calculará +
            +automaticamente os valores das partições Lógicas caso +as primeiras 4 partições forem +
            +ocupadas. +

    O próximo passo, é a localização +da partição no espaço livre existente o disco. As +duas opções disponíveis são: +
- Beginning : A partição é colocada +a partir do inicio do espaço livre no disco, ocupando o espaço +
                   +livre de acordo com o seu tamanho (do início para o fim do espaço +livre ), este é o +
                    +padrão para a criação de novas partições +e o mais utilizado. Veja o exemplo,  a +
                    +criação de uma partição de 30MB em um +disco com 50MB de espaço não +
                    +particionado, sendo que este disco já possui uma partição +de 120MB(com espaço +
                    +total de 170MB). +

              +##################################MMMMMMMMMMMMMMMMMMMMMM +
                    +|                                                                       +| +
               +Partição existente(120MB)                     +Espaço Livre(50MB) +
  +

              +com a nova partição criada: +

 ###################################################MMMMMMMMM +
                        +|                                                            +|                                   +| +
              +Partição existente(120MB)                    +Nova partição                   +Espaço +
                                                                             +(30MB)                            +Livre +

- End       : A partição +é criada subtraindo-se o espaço livre total do disco pelo +tamanho da +
                  +partição  que será criada, começando a +criar esta partição a partir do ponto que +
                  +resultou esta subtração. +
                  +Veja abaixo no exemplo, a partição que será criada +terá o tamanho de 30MB e existe +
                  +no disco um espaço não particionado de 50MB, com 120MB +já ocupados por uma +
                  +partição existente: +

              +##################################MMMMMMMMMMMMMMMMMMMMM +
                    +|                                                                         +| +
               +Partição existente(120MB)                         +Espaço Livre(50MB) +
  +

com a nova partição criada (Selecionando a opção +End): +

##################################MMMMMMMMMM################# +
                        +|                                                           +|                                  +| +
              +Partição existente(120MB)                       +Espaço                    +Nova partição +
                                                                                +Livre                          +(30MB) +

    A partição que será criada utilizara +o espaço livre entre o último Setor do disco e o setor resultante +da subtração(170MB-30MB). Mesmo assim, a ordem +que será criada esta partição partição +será criada do Setor inicial(que é o resultado da subtração) +para o último Setor do disco. Existirá um espaço livre +de 20MB entre a primeira partição (de 120MB) +e a nova partição de 30MB. +

+ +
+


2.3.9-) Print <p>

+ +

   Este comando mostra a tabela de partição +no formato selecionado na tela, ou permite que seja gravado um arquivo +no disco. Todas as partições são classificadas na +ordem que foram gravadas no disco. +

Os formatos aceitos para visualização de partições +são: +

RAW <r> : Formato de dados do disco, mostra os setores +que serão gravados para o disco, caso +
                   +seja escolhido o comando WRITE <W>. O formato mostrado é exatamente +aquele +
                   +que será gravado para ao disco. +
          Abaixo um exemplo +deste formato: +
        -------------------------------------------------------------------- +
          Disk Drive: +/dev/hda +
          Sector 0: +
          0x000: EB 69 +4C 49 4C 4F 01 00 14 00 D7 02 00 00 00 00 +
          0x010: FB 1B +CF 36 74 D8 80 23 01 75 D8 80 23 01 73 D8 +
          0x020: 80 23 +01 01 77 01 77 D8 80 23 01 78 D8 80 23 01 +
          0x030: 64 D8 +80 23 01 65 D8 80 23 01 66 D8 80 23 01 67 +
          0x040: D8 80 +23 01 68 D8 80 23 01 69 D8 80 23 01 6A D8 +
          0x050: 80 23 +01 6B D8 80 23 01 00 00 00 00 00 00 00 00 +
          0x060: 00 00 +00 00 00 00 00 00 00 00 00 B8 C0 07 8E D8 +
          0x070: 8C 06 +66 00 89 36 64 00 89 1E 68 00 88 16 6A 00 +
          0x080: B8 00 +9A 8E C0 B9 00 01 29 F6 29 FF FC F3 A5 EA +
          0x090: 94 00 +00 9A FA 8E D8 8E C0 BC 00 B0 B8 00 90 8E +
          0x0A0: D0 FB +B0 0D E8 57 00 B0 0A E8 52 00 B0 4C E8 4D +
          0x0B0: 00 BE +30 00 BB 00 10 FC AD 89 C1 AD 89 C2 09 C8 +
          0x0C0: 74 20 +46 E8 43 00 72 06 81 C3 00 02 EB EA 50 B0 +
          0x0D0: 20 E8 +2A 00 58 88 E0 E8 12 00 31 C0 88 C2 CD 13 +
          0x0E0: EB CF +B0 49 E8 17 00 EA 00 00 00 9B 50 C0 E8 04 +
          0x0F0: E8 01 +00 58 24 0F 04 30 3C 3A 72 02 04 07 30 FF +
          0x100: B4 0E +CD 10 C3 5A 59 5B C3 F6 C2 40 74 52 80 E2 +
          0x110: BF 53 +51 52 B4 08 CD 13 72 EB 88 F3 5A 88 16 6D +
          0x120: 01 88 +F2 30 F6 88 F7 58 51 86 CD D0 C5 D0 C5 80 +
          0x130: E5 03 +89 0E 6B 01 59 83 E1 3F F7 F1 FE C2 88 16 +
          0x140: 6E 01 +31 D2 43 F7 F3 88 D6 8A 16 6D 01 3B 06 6B +
          0x150: 01 77 +13 86 C4 D0 C8 D0 C8 0A 06 6E 01 89 C1 5B +
          0x160: B8 01 +02 CD 13 C3 5B 31 C0 F9 C3 00 00 00 00 00 +
          0x170: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x180: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x190: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1A0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1B0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 80 01 +
          0x1C0: 01 00 +0B FE 3F 8F 3F 00 00 00 51 4C 23 00 00 00 +
          0x1D0: 41 D7 +83 FE BF 6F 17 75 73 00 59 81 25 00 00 00 +
          0x1E0: 01 98 +05 FE 7F D6 98 42 25 00 7F 32 4E 00 00 00 +
          0x1F0: 81 70 +82 FE BF 72 70 F6 98 00 43 BC 00 00 55 AA +

          Sector 2441880: +
          0x000: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x010: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x020: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x030: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x040: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x050: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x060: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x070: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x080: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x090: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0A0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0B0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0C0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0D0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0E0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x0F0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x100: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x110: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x120: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x130: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x140: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x150: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x160: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x170: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x180: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x190: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1A0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1B0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 01 +
          0x1C0: 01 98 +0B FE 7F D6 3F 00 00 00 40 32 4E 00 00 00 +
          0x1D0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1E0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 +
          0x1F0: 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 55 AA +
          ----------------------------------------------------------------- +
               +A primeira tabela de partição mostrada é a Primária, +depois +
          as tabelas de +partições ligadas com cada partição lógica. +Como +
          no exemplo, +os dados são mostrados em bytes Hexadecimais(na +
          primeira coluna) +seguidos de 16 bytes por linha. +

Sector <s>: Mostra a tabela de partição +classificada por setores. Esta +
          opção +mostra o espaço não particionado no disco e a partição +
          Extendida, +que é mostrada antes das partições Lógicas. +
          Abaixo um exemplo +deste formato: +
          ------------------------------------------------------------------ +
          Partition Table +for /dev/hda +

                               +First         Last +
           # Type        +Sector     Sector     Offset   +Length   Filesystem Type (ID)   Flags +
          -- -------     +--------   ---------   ------ --------- ---------------------- +--------- +
           1 Primary        +0         2313359      +63  2313360  Win95 FAT32 (0B)   Boot (80) +
            +Logical      2313360  2441879        +0    128520  Free Space                +None (00) +
           3 Primary   +2441880  7566614        0  +5124735  Extended          +(05)   None (00) +
           5 Logical   +2441880   7566614      63  5124735  +Win95 FAT32 (0B)   None (00) +
           2 Primary  +7566615  10024559       0  2457945  +Linux                +(83)   None (00) +
           4 Primary +10024560 10072754       0      +48195  Linux Swap       (82)  None +(00) +
          ------------------------------------------------------------------------------------ +
          Onde: +
          #                  +- Identificação da partição no disco /dev/hda +
          Type            +- Tipo da partição(veja o exemplo) +
          First Sector +- Primeiro Setor utilizado para o armazanamento da partição. +
          Last Sector  +- Último Setor utilizado para o armazenamento da partição. +
          Offset           +- +
          Lenght         +- Tamanho total da partição em setores (Last Sector - First +
                                 +Sector). +
          FileSystem +Type (ID) - Identificação do Sistema de Arquivos da partição,  +seguido do seu +
                                  +código hexadecimal no CFDisk. A partição Extendida +é identificada como +
                                  +um sistema de arquivos  com o código 05 (veja o exemplo). +
          Flags        +-     Opções da partição +seguido de seu valor em  hexadecimal. +

Table <t> : Mostra a tabela de partição +classificada pelo número da partição. +
            +Esta opção deixa fora todo espaço livre e não +usado na partição. +
            +Abaixo um exemplo deste formato. +
            +---------------------------------------------------------------- +
            +Partition Table for /dev/hda +

                           +---Starting---         ----Ending----    +Start       Number of +
             +# Flags Head Sect Cyl   ID  Head Sect Cyl    +Sector      Sectors +
            +-- ----- ----   ----  ----  ----   ---- ---- +----  --------      --------- +
             +1  0x80    1     1       +0  0x0B  254   63  143           +63   2313297 +
             +2  0x00    0     1   +471  0x83  254   63  623  7566615   +2457945 +
             +3  0x00    0     1   +152  0x05  254   63  470  2441880   +5124735 +
             +4  0x00    0     1   +624  0x82  254   63  626 10024560      +48195 +
             +5  0x00    1     1   +152  0x0B  254   63  470            +63   5124672 +
             +------------------------------------------------------------------- +
           Onde: +
           #                 +- Número da partição de disco +
           Flags             +- As opções utilizadas com a partição (em  +valor Hexadecimal). +
                                      +O valor 0x80 equivale a BOOT. +
                                      +O valor 0x00 equivale a nenhuma opção  utilizada +naquela partição. +
           Starting +
           Head                       +- Cabeçote Inicial +
           Sector                     +- Setor Inicial +
           Cyl                          +- Cilindro Inicial +
           ID                           +- Identificação do Sistema de arquivos(em  hexadecimal, +conforme a +
                                               +tabela do CFdisk). +
           Ending +
           Head                       +- Cabeçote Final +
           Sector                     +- Setor Final +
           Cyl                          +- Cilindro Final +
           Start +Sector            +- Setor inicial da partição +
           Number +of Sectors - Número de setores ocupados pela partição. +

    Se a partição não inicia ou +não termina em um cilindro limite do disco ou se o seu tamanho não +é divisível pelo tamanho do cilindro, um * é +será mostrado após o setor não alinhado. Este problema +normalmente ocorre quando a partição é criada por +um Sistema operacional em que o limite da partição não +é alinhada com o cilindro ou que utiliza a contagem do tamanho do +disco +
de forma diferente. +
    A tabela de partição somente tem 10 +bits disponível para identificar o cilindro inicial e final. Assim, +quando o setor inicial absoluto é um cilindro maior que 1023(final +do disco), o valor máximo para a cabeça inicial, setor +e cilindro são definidos. Este metodo é usado pelo OS/2, +e +
e corrige os problemas associados com OS/2 caso o Fdisk regrava +a tabela de partição quanto ela não esta neste formato. +
    Desde então Linux e OS/2 utilizam +esta contagem de setores absolutos, os valores na cabeça inicial +e final, Setor e Cilindro não são usadas. +

+ +
+


2.3.10-) Quit <q>

+ +

     Esta opção faz com que o CFdisk +abandonar todas as alterações e retornar para o Aviso de +comando. Quando esta opção é escolhida, o programa +retorna deixando o disco como estava antes de se iniciar o particionamento. +
     Se escolher esta opção o CFdisk +abandonará o particionamento de disco e voltará para a linha +de comandos imediatamente. Se alterar/criar/excluir alguma partição +de disco e escolher esta opção, o programa emitirá +um Beep indicando que alguma alteração feita no disco foi +abandonada. +

OBS: Esta opção é útil caso tenha +se cometido algum engano durante o particionamento do disco, +
          como apagar +por uma partição que contém arquivos, alterar o tamanho +do disco(geometria), +
          etc. Lembre-se +que tudo o que fez será abandonado, durante o particionamento, se +escolher +
          esta opção. +

+ +
+


2.3.11-) Type <t>

+ +

     Comando usado para alterar o tipo do sistema +de arquivos utilizado pela partição. As partições, +quando criadas, recebem o sistema de arquivos Linux Native(ou simplesmente +Linux - tipo 83). O CFdisk pode criar, manipular, excluir, uma grande +variedade de Sistemas de arquivos para os mais diversos tipos de sistemas +operacionais existentes, veja o final deste manual para ver as partições +compatíveis com este programa. +
   Para alterar o tipo do sistema de arquivos (File System) +utilizado pela partição, tecle <t>, e digite o valor de +acordo com a lista de partições disponíveis no programa. +
   Por exemplo, para mudar a partição do tipo +Linux para Linux Swap, selecione esta partição, e tecle <t>, +e digite o número 82(que corresponde a Linux Native) +e tecle <Enter>, e a partição terá seu sistema +de arquivos alterado. +

+ +
+


2.3.12-) Units <u>

+ +

     A função deste comando é +alterar as unidades de medida do tamanho da partição que +é mostrado na tela, por padrão, ele é mostrado em +MegaBytes. +
    As unidades de medida do tamanho da partição +são em MegaBytes, Cilindros e Setores ocupados pela partição +de disco. +
Abaixo um exemplo da mudança da unidade de medida para Cilindros. +
---------------------------------------------------------------------------------------------------- +

CFdisk 0.8l +
Disk Drive: /dev/hda +
Heads:255  Sectors:63  Cilinders:627
+---------------------------------------------------------------------------------------------------- +
Name            +Flags             +Part Type           FSType                +[LABEL]         Cilinders +
hda1              +Boot              +Primary       Win 95 FAT 32                                    +249 +
hda5                                    +Logical     DOS FAT 16 (BIG)   GLEYDSON         +22 +
                                           +Pri/Log           Free +Space                                        +371 +
  +
  +
  +
  +
  +
  +
  +
  +
  +

[Bootable]   [Delete]   [Help]   [Maximize]   +[Print] +
[Quit]          [Type]     +[Units]   [Write] +
---------------------------------------------------------------------------------------------------- +
   Será mostrada a quantidade de cilindros que a partição +ocupa no disco ao invés do espaço em MB. +

+ +
+


2.3.13-) Write <W>

+ +

      Este comando grava todas as tabelas de +partições criadas/modificadas e excluidas para o disco. Só +é aceita a tecla <W> em maiúscula para gravação +da partição de disco, por motivos de segurança para +que não seja feita a gravação acidental das partições +enquando estiver utilizando o programa. Para quem utiliza as setas do teclado, +o método é o mesmo que as outras opções. +
     Após selecionar esta opção, +o CFdisk perguntará se confirma a gravação das partições +para o disco. +
Para gravar a partição, digite "yes" e tecle <Enter>. +
Para cancelar o comando, pressione <Esc> ou digite "no" e +tecle <Enter>. +

    Após confirmar com "yes", o CFdisk +gravará a tabela de partição no disco e fara o Kernel +re-ler a tabela de partição do disco, para se evitar reiniciar +o sistema para utilizar a nova tabela de partição. +
    A tentativa de re-leitura da tabela de partição +pode falhar. Para solucionar este problema, é preciso reiniciar +o computador, quando o computador é reiniciado, o sistema operacional +faz uma nova leitura das tabelas de partições existentes +no disco, fazendo com que sejam reconhecidas +
corretamente. +

+ +
+


3-) Tipos de partições +compatíveis com o CFdisk

+ +

  Abaixo uma listagem das partições compatíveis +com o programa CFdisk e seus respectivos códigos Hexadecimais, +para consulta técnica ou utilização durante o particionamento +de disco. +

Código   Nome +
01 -         DOS FAT12 +
02 -         Xenix root +
03 -         Xenix usr +
04 -         DOS FAT16 (<32MB) +
05 -         Extendida +
06 -         DOS FAT16 (>=32MB) +
07 -         OS/2 HPFS ou NTFS +
08 -         AIX +
09 -         AIX inicializável +
0A -         OS/2 Boot Manager +
0B -         Windows 95 FAT32 +
0C -         Windows 95 FAT32(LBA) +
0E -         Windows 95 FAT16(LBA) +
0F -         Windows 95 Extendida +
11 -         DOS FAT12 oculta +
12 -         DOS FAT16 oculta +
16 -         DOS FAT16 oculta +
17 -         HPFS OS/2 oculta +
40 -         Venix 80286 +
51 -         Novell +
52 -         Microport +
63 -         GNU Hurd +
64 -         Novell Netware +286 +
65 -         Novell Netware +386 +
75 -         PC/IX +
80 -         Minix Antigo +
81 -         Linux / Minix +
82 -         Linux Swap +
83 -         Linux Nativa +
85 -         Linux Extendida +
93 -         Amoeba +
94 -         Amoeba BBT +
A5 -         BSD/386 +
A6 -         Open BSD +
A7 -         NextStep +
B7 -         BSDI Sistema de +Arquivos +
B8 -         BSDI Swap +
C7 -         Syrinx +
DB -         CP/M +
E1 -         DOS access +
E3 -         DOS R/O +
F2 -         DOS secundária +
FF -         BBT +

+ +
+


4- ) Direitos Autorais

+ +

      Este documento foi desenvolvido com base +em minha experiência e conhecimento em discos e partições, +mediante pesquisa em alguns documentos como os How-TO do Linux e verificando +as principais dúvidas de usuários durante a utilização +de particionadores de disco, tendo como objetivo levar o conhecimento sobre +discos, partições e utilização deste programa, +atendendo tanto usuários iniciantes como avançados e como +contribuição para a comunidade Linux em geral. +

+

Gleydson M. da Silva (gleydson_s@yahoo.com e gleydson@linuxbr.com.br)

+ +

    Qualquer dúvida, sugestão ou reclamação +podem ser mandadas para um dos E-Mail's Acima. Conto com sua contribuição +para a melhoria deste Manual. +

    Autorizo a reprodução Total ou parcial +deste texto para que seja utilizado para fins educativos, autoaprendizado, +colocação em Home pages e qualquer outra forma de distribuição +não comercial do documento desde que sejam mantidos os meus créditos +pela pesquisa e elaboração deste documento de acordo com +os termos da GNU (veja abaixo Licenças e Garantias +sobre este documento). +

+ +
+


5- ) Licenças e Garantias +sobre este documento

+ +

CFdisk-Portuguese copyright (C) 1999 Gleydson M. da Silva +

   Este documento é de livre distribuição, +que pode ser copiado e distribuído sob os termos da Licença +Pública Geral  GNU, conforme publicada pela Free Software Foundation, +versão 2 da licença ou (a critério do autor) qualquer +versão posterior. +

   Este documento é distribuído com a itenção +de ser útil ao seu utilizador, no entanto NÃO TEM NENHUMA +GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS OU +DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença +Pública Geral  GNU para maiores detalhes. +

gleydson_s@yahoo.com +
gleydson@linuxbr.com.br +

+ +
+


6- ) Nota sobre Marcas Registradas

+ +

Os programas mencionados neste manual são de propriedade dos +seus respectivos donos: +

MS-DOS, Windows 3.1x, Windows 9x, Windows NT são de propriedade +da Microsoft. +
OS/2 e OS/2 Warp são de propriedade da IBM +

+ +
+


7- ) Agradecimentos

+ +

Agradeço a todas as pessoas que me mandam correções, +comentários, críticas e elogios sobre este documento, pois +através destas mensagens, estão contribuindo para a melhoria +deste projeto. +

Agradecimentos especiais a: +

Eduardo Marcel Macan <macan@thecore.com.br> - Pelo +apoio e interesse na divulgação +
                          +deste projeto e outros documentos relacionados com a tradução +e divulgação de +
                          +documentos do Linux no Brasil. +
Jorge Godoy <jorge@bestway.com.br> - Pela revisão +deste documento e primeiras orientações +
                          +para a conversão deste para SGML. +
Adam di Carlo <adam@onshore.com> - Que me deu apoio +na colocação deste +
                          +documento  na documentação da distribuição +Debian. +

E a voce pelo enteresse em conhecer mais sobre o Linux.  +

+ +
  +

<EOF> + + diff --git a/fdisk/doc/CFdisk-Portuguese.txt b/fdisk/doc/CFdisk-Portuguese.txt new file mode 100644 index 00000000..99981c4d --- /dev/null +++ b/fdisk/doc/CFdisk-Portuguese.txt @@ -0,0 +1,1236 @@ + CFdisk-Portuguese Copyright (C) 1999 Gleydson M. da Silva + + + + + + + + Gleydson M. da Silva - gleydson@linuxbr.com.br + Versão: 1.68 + + + + + + + +[ Indice ] + +1 - Introdução ao CFdisk + 1.1 - O que é uma partição de disco + 1.2 - O que é a tabela de partição + 1.3 - Introdução ao Particionamento de Discos + 1.4 - Identificadores utilizados neste manual + 1.5 - Identificação de discos e partições no Sistema Linux + 1.6 - Tipos de partições de disco + 1.7 - Observações sobre o formato DOS 6.xx(FAT16) + +2 - Iniciando o programa CFdisk + 2.1 - Opções de Linha de comando + 2.2 - Conhecendo a tela do CFdisk + 2.3 - Descrição dos comandos + 2.3.1 - Setas Acima/Abaixo - Esquerda/Direita + 2.3.2 - + + 2.3.3 - Boot + 2.3.4 - Delete + 2.3.5 - Geometry + 2.3.6 - Help + 2.3.7 - Maximize + 2.3.8 - New + 2.3.9 - Print + 2.3.10 - Quit + 2.3.11 - Type + 2.3.12 - Units + 2.3.13 - Write + +3 - Tipos de partições compatíveis com o CFdisk + +4 - Direitos Autorais + +5 - Licenças e Garantias sobre este documento + +6 - Notas sobre marcas registradas + +7 - Agradecimentos + + + + + + + + + + + +1-) Introdução ao CFdisk + +CFdisk é um programa utilizado para fazer o particionamento de discos, +utilizando uma interface em modo texto. + +A grande características deste programa, além de sua interface de comunicação +com o usuário e a enorme quantidade de partições que manipula, é a grande +facilidade de operação, o seu poder de manipulação de partições e a sua +precisão que fazem com que o usuário tenha mais confiança durante o +particionamento de disco. + +É recomendável a leitura deste texto, mesmo que tenha uma noção sobre o +particionamento de discos, exceto para os gurus que já conhecem a fundo a +forma de trabalho, em geral, de programas deste tipo, pois o particionamento +de disco pode destruir os seus arquivos e partições já existentes, se for +usado de forma incorreta. + +O programa CFdisk pode ser utilizado em qualquer sistema operacional que +esteja de acordo com o padrão POSIX (Linux, UNIX, FreeBSD, HPUX, etc). + +A versão do CFdisk utilizada nas explicações deste manual é a 0.8, mas +isto não impede que este manual seja utilizado com versões futuras ou +anteriores deste programa. As características principais +do programa CFdisk e as explicações sobre particionamento, são válidas para +quaisquer versões deste programa. + +Este documento é distribuído com a itenção de ser útil ao seu utilizador, +no entanto NÃO TEM NENHUMA GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS +OU DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença Pública +Geral  GNU para maiores detalhes. + + +1.1-) Partição de Disco + +Uma partição de disco é o local onde o sistema operacional armazena seu +sistema de arquivos(arquivos, diretórios, FAT, boot sector, etc). + + + +1.2-) Tabela de partição + +A Tabela de partição é o local do disco rígido onde se localizam os dados sobre +todas as partições existentes no disco como o sistema de arquivos utilizado, se +ela é inicializável, a cabeça inicial/final, setor inicial/final, cilindro +inicial/final, número de setores ocupados por ela no disco. + + +1.3-) Introdução ao particionamento de discos + +Particionar o disco rígido é dividir ele em partes para armazenamento +de arquivos e programas. As partições criadas no disco podem ter o tamanho +que desejar (desde que esteja dentro da capacidade máxima do disco rígido). + +Uma partição não interfere em outras partições do mesmo disco(é como +se tivessemos vários discos rígidos dentro de um), e nem em outros discos +rígidos(caso possuir mais que um disco rígido instalado em seu computador). + +Pode ser criada uma partição única, que neste caso todo o disco rígido +é usado para armazenar os arquivos(que é o caso mais comum caso voce tenha +o DOS), ou várias partições, que podem ser usadas pelo mesmo SO(Sistema +Operacional) ou outros sistemas operacionais diferentes(um exemplo de várias +partições: se for usar o DOS e o Linux no mesmo disco, os dois sistemas vão +estar no mesmo disco mas um não interfere no outro). + +ATENÇÃO : A OPERAÇÃO DE PARTICIONAMENTO DE DISCOS PODE FAZER COM QUE OS DADOS + ARMAZENADOS EM SEU DISCO RÍGIDO SEJAM PERDIDOS, SE FOR USADA + INCORRETAMENTE. É SEMPRE RECOMENDADO RETIRAR UMA CÓPIA DE SEGURANÇA + DOS SEUS ARQUIVOS EXISTENTES NO MICRO ANTES DE SE EXECUTAR UM + PROGRAMA DESTE TIPO, A NÃO SER QUE TENHA CONFIANÇA NO QUE ESTA + FAZENDO E QUE ENTENDEU AS EXPLICAÇÕES SOBRE A IDENTIFICAÇÃO DE + DISCOS RÍGIDOS E SUAS PARTIÇÕES NO SISTEMA. + +Neste manual voce aprenderá como deve particionar seu disco rígido para +a instalação do SO usando o programa CFdisk. + + +1.4-) Algumas identificações utilizadas neste manual para facilitar a + compreensão do texto + +Esta parte descreve algumas características de organização deste manual e +algumas identificações que utilizei para facilitar o seu entendimento, e as +explicações que serão dadas. + +Explicação de nomes e comandos, sera seguida da palavra "onde:" e abaixo +dela as explicações sobre os comandos, exemplo: + +onde: +nome a ser explicado1 : Descrição +nome a ser explicado2 : Descrição +nome a ser explicado3 : Descrição + +ou + +onde: +nome a ser explicado1 - Descrição +nome a ser explicado2 - Descrição +nome a ser explicado3 - Descrição + + +Quando for feita alguma referência com tecla do teclado, por exemplo, +pressione p para listar as partições, a letra sera colocada entre <> para +que seja melhor entendida: + +pressione para deletar uma partição... +...pressione para escolher a opção do menu. +pressione para listar os tipos de partições disponíveis... + + + As linhas pontilhadas que aparecem na tela, veja abaixo, +---------------------------------------------------------------------------- +---------------------------------------------------------------------------- +servem para identificar que o que esta entre as linhas é um exemplo de como +será a resposta do comando para a tela de seu computador. + + + +1.5-) Identificação de discos e partições no Linux + +Antes de descrever como se utiliza o programa CFdisk, é importante fazer +algumas explicações sobre a identificação das partições e unidades de disco +no sistema Linux( e outros *nix). + +Se voce for um usuário que já conhece a interpretação de discos e partições +neste sistema, voce não precisará ler esta parte. + +No sistema operacional Linux, os dispositivos existentes no computador +(como impressoras, unidades de disquetes, discos rígidos, monitor, placa de +som, etc...) são identificados por um nome referente a este dispositivo e +colocado no diretório /dev (que é utilizado para identificar os dispositivos +ou periféricos existentes no computador). + + A identificação dos discos rígidos segue a seguinte forma: + + /dev/hda1 + | | || + | | ||_Número que identifica a partição do disco rígido(1=Primeira, 2=segunda) + | | | + | | |_Letra que identifica o disco rígido(a=primeiro disco, b=segundo disco, etc..) + | | + | |_Sigla HD - Significa que é um disco rígido IDE(Se tiver um SD significa SCSI) + | + |_ Identificação do diretório onde os dispositivos do sistema são armazenados + +OBS: As unidades de disco rígido SCSI, são identificadas com as letras SD + seguida pela letra da unidade e número da partição e os discos IDE são + identificados por HD seguida pela letra da unidade de disco e o número + da partição do disco(como visto acima). + +Abaixo, algumas identificações de disco do sistema Linux: + +/dev/hda1 - Disco rígido IDE primário principal - Primeira partição +/dev/hda2 - Disco rígido IDE primário principal - Segunda partição +/dev/hda3 - Disco rígido IDE primário principal - Terceira partição +/dev/hdb1 - Disco rígido IDE primário escravo - Primeira partição +/dev/hdb2 - Disco rígido IDE primário escravo - Segunda partição +/dev/hdb3 - Disco rígido IDE primário escravo - Terceira partição +/dev/hdc1 - Disco rígido IDE secundário principal - Primeira partição +/dev/hdc2 - Disco rígido IDE secundário principal - Segunda partição +/dev/hdc3 - Disco rígido IDE secundário principal - Terceira partição +/dev/hdd1 - Disco rígido IDE secundário escravo - Primeira partição +/dev/hdd2 - Disco rígido IDE secundário escravo - Segunda partição +/dev/hdd3 - Disco rígido IDE secundário escravo - Terceira partição +/dev/sda1 - Primeiro disco rígido SCSI - Primeira partição +/dev/sda2 - Primeiro disco rígido SCSI - Segunda partição +/dev/sda3 - Primeiro disco rígido SCSI - Terceira partição +/dev/sdb1 - Segundo disco rígido SCSI - Primeira partição +/dev/sdb2 - Segundo disco rígido SCSI - Segunda partição +/dev/sdb3 - Segundo disco rígido SCSI - Terceira partição + +No exemplo acima foram usadas 3 partições por disco, mas podem existir mais +partições no mesmo disco, um exemplo é se o disco rígido possuir partições +Lógicas, que são identificadas no sistemas a partir de /dev/hdx5. + + + +Abaixo um exemplo de como o Linux identifica as partições em cada disco +existente em seu computador: + +Vamos supor que eu tenha 2 discos rígidos: +o 1ºdisco de 2GB e o 2ºdisco de 1GB(Giga Byte ou 1.000 Megas!) + +No primeiro disco(de 2GB), a primeira partição é de 800MB do tipo +FAT16(DOS), a segunda partição é de 1.2GB do tipo EXT2(Linux)(1.2GB+800MB=2GB +que é a capacidade total do disco). Então as partições seriam identificadas +da seguinte forma no Linux: + +/dev/hda - Disco rígido Primário Principal +/dev/hda1 - Primeira partição do primeiro disco rígido (de 800MB do tipo DOS) +/dev/hda2 - Segunda partição do primeiro disco rígido( de 1.2GB do tipo Linux) + +Neste caso estariam disponíveis 800MB para serem usados com o DOS e +1.2GB para o Linux. + +Por exemplo, se voce particionar um disco rígido em duas partes e usar +as duas partições no DOS, ele reconhecerá as partições como sendo C: e D:. + +Lembre-se: Quando um disco é particionado, nenhuma partição interfere + na outra, repare que quando voce particiona(divide) um disco, + é como se tivesse dois discos rígidos(o único cuidado que + voce deve tomar é com as cópias de segurança, porque se der + um problema de parte eletrônica no disco rígido, por exemplo, + a sua placa controladora queimar ou o cabeçote dele ir pro + espaço, voce perderá as suas 2 partições que estão armazenadas + nele. + + +Voltando ao exemplo das classificações das partições do disco, vamos +para o segundo disco: + +No segundo disco(1GB), eu tenho uma partição de 950MB do tipo FAT16(DOS), +que costumo usar para armazenar arquivos temporários e cópias de segurança +de meu sistema, etc..., e outra de 50MB SWAP(Partição de memória virtual +como descrevi acima)(950MB+50MB=1GB). Então as partições deste disco seriam +identificadas da seguinte forma no Linux: + +/dev/hdb - Disco rígido principal escravo +/dev/hdb1 - Primeira partição do disco acima ( de 950MB do tipo DOS) +/dev/hdb2 - Segunda partição do disco acima ( de 50MB do tipo SWAP) + +No disco acima, 950MB estão disponíveis para serem usados pelo DOS e +50 MB pela memória virtual (SWAP) do Linux. + +Note que se voce utiliza o MS-DOS, voce não conseguirá ver as partições +do Linux e SWAP, porque são imcompatíveis com o formato aceito pelo DOS (ele +identificaria a primeira partição do primeiro disco(800MB) como a unidade C: +e a primeira partição do segundo disco(950MB) como unidade D), mas o +contrário não acontece; O Linux tem total compatibilidade com a partição +DOS FAT12, FAT16, FAT32, OS/2 HPFS, e muitas outras. + + + +1.6-)Tipos de partições de discos + +As partições de disco são divididas em tres tipos: Primária, Extendida +e Lógica. +Pode se ter, no máximo, 4 partições Primárias e Extendidas no mesmo disco +(3 Primárias e 1 Extendida ou 4 partições Primárias em cada disco). +A partição Primária permite o armazenamento de arquivos e diretórios. + +Todos os computadores que possuem somente a unidade C(supondo que utilize +o DOS), utilizam este tipo de partição para armazenamento de arquivos e +inicialização do sistema operacional. + +Se for preciso criar mais que 4 partições no mesmo disco, será necessário +criar uma partição Extendida. A partição Extendida não pode ser utilizada +para armazenar arquivos. Ela é usada para a criação de outras partições, +dentro dela, que são chamadas de partições Lógicas. + +Uma partição extendida podem conter várias partições Lógicas. As partições +Lógicas podem armazenar arquivos e diretórios(como as partições primárias). + +Um mesmo disco rígido pode armazenar mais de 64 partições independentes +uma das outras. + +LEMBRE-SE: Os arquivos e diretórios podem ser armazenados somente em + partições de disco primárias ou lógicas, a partição extendida não + é usada para armazanamento de arquivos e diretórios. + +Se possuir duas partições em seu computador (C: e D: no DOS), e não +estiver usando a partição D:, a instalação pode ser feita nesta partição +desde que ela tenha o espaço necessário para o sistema operacional Linux, +os programas que desejar instalar, mais a partição SWAP. + + + +1.7-) Observações sobre o formato DOS 6.XX(FAT 16) + +No formato DOS 6.XX(FAT16), o primeiro setor da área de dados da partição +é utilizado frequentemente pelo DOS para armazenamento de dados sobre a +partição de disco, e estes dados são usados pelo sistema para se ter maior +confiabilidade do que os dados armazenados na tabela de partição. O sistema +de arquivos DOS, faz o FDISK(do DOS) limpar os primeiros 512 bytes da área +de dados da partição sempre que uma mudança de tamanho acontecer. + +O formatador do DOS(format) verifica este primeiro setor toda vez que +a upção /U (que é utilizada para não salvar dados para se fazer a desformatação +do disco) é utilizada. + +Isto é considerado uma FALHA no Format(do DOS) e no Fdisk(do DOS). +A opção abaixo deve ser utilizada caso voce crie uma partição do DOS FAT16 +com o CFdisk, que faz com que os primeiros 512 bytes daquela partição +sejam "limpos", para manter a compatibilidade com o DOS. Utilize esta opção +dentro do Linux, após criar a partição com o CFdisk e reiniciar o seu +computador. Foi notado que esta opção só funciona corretamente somente quando +o Sistema Linux estiver instalado em seu computador. Não me responsabilizo +caso utiliza-la a partir de um disquete de recuperação. + +dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 + +onde: +hdx1 - É a identificação da unidade de disco e a partição que foi criada + pelo CFdisk utilizando o sistema de arquivos DOS que terá seu + primeiro setor "limpo". + + +OBS1: Cuidado ao utilizar esta opção, um pequeno descuido pode resultar na + perda de dados do seu disco rígido ou outras partição. + +OBS2: Não utilize este comando com partições que utilizam o sistema de arquivos + FAT32(utilizada nos sistemas operacionais Windows 95 OSR/2 e superiores) + se for utilizada em um disco com este sistema, sua FAT será corrompida, + se isto acontecer, será necessária a re-formatação da partição. + +OBS3: É extremamente recomendado que se utilize o programa de particionamento + que acompanha o seu sistema operacional. Por exemplo, se deseja criar + uma partição DOS 6.XX, utilize o FDisk qua acompanha o DOS. + + + +2-) Iniciando o programa CFdisk + +Para entrar no programa CFdisk digite: +cfdisk + +onde: +unidade - é a unidade de disco que deseja utilizar para fazer o particionamento + a unidade pode ser: /dev/hda, /dev/hdb, /dev/hdc ..., /dev/sda, + /dev/sdb...,etc + +NOTA: Se voce não digitar a unidade, o cfdisk utilizará a unidade /dev/hda + como padrão. + + + +2.1-) Opções de linha de comando utilizadas com o CFdisk + +Opções de linha de comando fazem com que o programa inicie de forma +específica ou personalizada. As opções devem ser digitadas após o nome do +programa (cfdisk). + + cfdisk < -avz > < -c cilindros > < -h cabeçotes > + < -s setores_por trilha > < -P opt > < dispositivo > + +onde: +-a Usa um cursor seta ao invés de video reverso para destacar a + partição atual. +-v Mostra a versão do programa e Coyright(Direitos Reservados). +-z Ignora a leitura da tabela das partições existentes no disco + ao iniciar o CFdisk. + +-c Número de Cilindros do disco +-h Número de Cabeçotes do disco +-s Setores por trilha existentes no disco. +-P OPC Mostra a tabela de partição no formato especifico. + OPC - Pode ser: r - Mostra a tabela de partição em Formato RAW + s - Mostra a tabela de partição em Format de Setores + t - Mostra a tabela de partição classificada por + setores + Para maiores detalhes, veja O comando Print

. + +OBS: A utilização dos parâmetros -c -h -s, substituirão os parâmetros da BIOS + da placa, utilize estas opções se sua bios não utilizar estes parâmetros + ou se mostrar valores incorretos. + +Após entrar o programa CFdisk, ele verificará automaticamente o +tamanho do Disco Rígido, se não conseguir, o programa será terminado. +Para resolver este problema, especifique o tamanho do disco em cilindros, +cabeças, e setores na linha de comando que inicia o programa. +Este problema geralmente acontece quando se tenta particionar uma unidade de +disco SCSI que esteja conectada a uma placa controladora que não possui BIOS, +e quando uma BIOS mostra os valores da geometria do disco(tamanho) +incorretamente. + +O próximo passo do CFdisk é fazer a leitura das partições atuais do +disco, se não conseguir, o programa será terminado. O único motivo para o +CFdisk mostrar esta mensagem de erro, é se voce digitar parâmetros +incorretos para o tamanho do disco, caso tenha acontecido o problema +descrito no paragrafo anterior. Verifique se os parâmetros foram digitados +incorretamente, se os parâmetros estiverem digitados corretamente e mesmo +assim o programa continua dando erro na leitura das partições, utilize a +opção -z na linha de comando do programa, que faz com que ele ignore a +leitura das partições existentes no disco ao iniciar. + + + +2.2-) Conhecendo a Tela do CFdisk + +Após digitar CFdisk, será mostrada a tela principal onde voce poderá +acionar os comandos para manipulação das partições de disco, e visualizar +as partições de disco atuais e outros dados. Abaixo o exemplo e explicações +sobre esta tela. + +O disco utilizado para os exemplos é um disco de 5157 MB de Capacidade com: +- 10672 Cilindros 15 Cabeças 63 Setores (no modo C/H/S) +- 627 Cilindros 255 Cabeças 63 Setores (no modo LBA) + + A unidade de medida utilizada pelo CFdisk para mostrar os parâmetros do +disco será o mesmo configurado na BIOS, ou seja, se estiver utilizando o +disco com o modo de operação em LBA, os valores de cilindros, cabeças e +setores motrados pelo CFdisk sera em LBA. + + +---------------------------------------------------------------------------- + CFdisk 0.8l + + Disk Drive: /dev/hda + Heads:255 Sectores per track:63 Cylinders:627 +----------------------------------------------------------------------------- +Name Flags Part Type FSType [LABEL] Size(MB) +hda1 Boot Primary Win 95 FAT 32 1953.12 +hda5 Logical DOS FAT 16 (BIG) GLEYDSON 172.58 + Pri/Log Free Space 2910.55 + + + + + + + + + + +[Bootable] [Delete] [Help] [Maximize] [Print] +[Quit] [Type] [Units] [Write] +---------------------------------------------------------------------------- +No cabeçalho da tela, é mostrada a versão do programa, a unidade de disco +que será usada no particionamento e os parâmetros de tamanho do disco(cabeçotes, +cilindros e setores). +Abaixo do cabeçalho após a linha pontilhada, se encontra a área das partições. + +onde: +- Name : é o nome da(s) partição(ões) de Disco. +- Flags : Se estiver marcada como BOOT, será possível iniciar o sistema + a partir desta partição(quando não se utiliza um Boot Manager). + Se estiver marcada como NC (Não compatível) significa que esta + partição não é compatível com o DOS, OS/2, etc. Para maiores + detalhes, veja O comando Maximize . +- Type : O tipo da partição pode ser Primária ou Lógica. Para espaço não + utilizado no Disco, o tipo da partição pode ser Primário/Log. +- FileSystems : Tipo de Sistema de Arquivos que é usado naquela partição. + Se o sistema de arquivos for desconhecido, ele será mostrado como + um valor Hexadecimal. + Um caso especial ocorre quando há Partições do Disco Rígido que + não podem ser usadas ( porque toda a partição primária esta em uso). + Quando isto é detectado, o tipo de FileSystems é mostrado como não + usável(Unusable) para criação de novas partições. +- Label : Nome de volume da partição de disco. Os nomes de partições FAT32, + não são mostrados com esta versão do CFdisk. +- Size : Mostra o tamanho que cada partição ocupa no disco rígido em + MegaBytes (por padrão). Também pode mostrar o tamanho ocupado por + Setores ou Cilindros. Se for mostrado um asterisco (*) após o + tamanho, isto diz que a partição não esta alinhada com Cilindro. + + +O espaço livre existente no disco para criação de novas partições, é +mostrado como uma outra partição, com o FSType(sistema de arquivos) Free +Space(espaço Livre). + +OBS: As partições de disco Extendidas não são mostradas na tela do CFdisk + durante o particionamento, mesmo assim, as partições lógicas que este + tipo de partição armazena, serão mostradas. + +No rodapé da tela, encontramos os comandos utilizados pelo CFdisk para +manipular as partições de disco. Os comandos são mostrados entre Chaves []. + +Todos os comandos no rodapé da tela, são aplicaveis somente para a +partição que estiver destacada com a barra(video reverso). Veja descrições +dos comandos do CFdisk para mais detalhes. + +Abaixo do rodapé da tela, é mostrada a descrição do comando que estiver +em destaque com o cursor em video reverso. + + Veja abaixo a tradução da tela principal do programa CFdisk: +---------------------------------------------------------------------------- + CFdisk 0.8l + + Unidade de Disco: /dev/hda + Cabeças:255 Setores por trilha:63 Cilindros:627 +----------------------------------------------------------------------------- +Nome Opções Tipo Part. Tipo Sist. Arquivos [VOLUME] Tamanho(MB) +hda1 Boot Primary Win 95 FAT 32 1953.12 +hda5 Logical DOS FAT 16 (BIG) GLEYDSON 172.58 + Pri/Log Espaço Livre 2910.55 + + + + + + + + + + +[Inicializável] [Apagar] [Ajuda] [Maximizar] [Imprimir] +[Sair] [Tipo] [Unidades][Gravar] +---------------------------------------------------------------------------- + + + +2.3-) Descrição dos comandos do CFdisk + +Os comandos do programa são utilizados criar partições, entrar na ajuda do +programa, alterar o tipo da partição, apagar uma partição, etc. + +Pode ser utilizado Seta p/ Esquerda e Seta p/ direita para se movimentar +entre os comandos, quando o cursor estiver em cima do comando que deseja +executar, pressione . + +Outro método que se pode utilizar para acionar uma opção do CFdisk, é +pressionando a primeira letra de cada opção, automaticamente a opção é +executada(sem ter que pressionar ). Neste método, todos os comandos +aceitam letras maiúsculas e minúsculas, exceto o comando Write(gravar +partição) que é executado somente se pressionar maiúscula, para evitar +gravações acidentais o disco. + +Quando estiver em um Sub-Menu e desejar retornar ao menu principal, +pressione a tecla . + + + +2.3.1-) Setas Acima e Abaixo/ Esquerda e Direita (Movimentação do Cursor) + +Setas Acima e Abaixo são utilizadas para se movimentar entre as partições +existentes no disco e espaço livre, selecionando-a para que seja utilizada +as opções do CFdisk. + +Setas Esquerda e Direita são utilizadas para selecionar entre as opções +diponíveis do programa(que serão explicadas abaixo). Para confirmar uma +opção, pressione . + + + +2.3.2-) O comando + + +Este comando é utilizado para atualizar a tela manualmente caso a +atualização automática falhar, por exemplo, quando uma partição for +excluida, e continuar a ser mostrada na tela. + + + +2.3.3-) O comando Boot + +Este comando permite escolher se a partição Primária atual será utilizada +para iniciar o sistema(BOOT). Selecione esta opção para selecionar entre +partição inicializável ou não inializável. Quando uma partição estiver +marcada como inicializável, aparecerá a palavra BOOT na coluna Flags(na tela +principal do programa). + +OBS: Não será necessário marcar a partição Linux como inicializável, caso se + esteja utilizando um Boot Manager para escolher qual sistema operacional + sera utilizado para inicializar o sistema. + + + +2.3.4-) O comando Delete + +Este comando apaga a partição selecionada do disco. Após apagar a partição, +o espaço ocupado por ela é convertido para espaço livre. +A partição marcada atualmente como Free Space ou como Unusable não pode +ser apagada. + + + +2.3.5-) O comando Geometry + +Este comando não é mostrado no menu, pois é utilizado para alterar o +tamanho (Cilindros, Cabeças e Setores do disco). Este comando só pode +ser acionado se for pressionada a tecla . + +ALERTA: Esta opção é recomendada somente para aqueles que sabem os riscos + que o uso desta opção pode fazer, e se a situação que estão, requerem + o seu uso. + +Uma situação que esta opção é util, é se o BIOS do seu computador não +mostrar corretamente os parâmetros do disco(Cilindros, Cabeçotes ou Setores), +sendo necessário que se passe manualmente o tamanho do disco para que seja +feito o correto particionamento do disco. + +OBS: Caso seu disco rígido for SCSI e placa controladora dele não tiver BIOS, + provavelmente o CFdisk não será iniciado. Se este problema ocorrer, + digite os parâmetros do disco na linha de comando ao iniciar o programa. + Para maiores detalhes, veja opções de linha de comando do CFdisk. + +Após pressionar será mostrada a seguinte tela: + +---------------------------------------------------------------------------- + CFdisk 0.8l + + Disk Drive: /dev/hda + Heads:255 Sectors:63 Cilinders:627 +----------------------------------------------------------------------------- +Name Flags Part Type File System [LABEL] Size(MB) +hda1 Boot Primary Win 95 FAT 32 1953.12 +hda5 Logical DOS FAT 16 (BIG) GLEYDSON 172.58 + Pri/Log Espaço Livre 2910.55 + + + + + + + + + +[ Cylinders] [Heads] [Sectors] [Done] + +---------------------------------------------------------------------------- +onde: +Cylinders: Altera o número de Cilindros do disco atual durante o particionamento. +Heads : Altera o número de Cabeças do disco atual durante o particionamento. +Sectors : Altera o número de Setores do disco atual durante o particionamento. +Done : Quando finalizar as alterações, tecle ou selecione Done para + que o CFdisk modifique os valores de Cilindros, Cabeças e Setores + que utiliza para particionar o disco e retorne a tela anterior. + + + Quando escolher algum parâmetro acima para alteração(Cilindros, cabeçotes +ou Setores do disco), será vista uma tela como esta: +---------------------------------------------------------------------------- + CFdisk 0.8l + + Unidade de Disco: /dev/hda + Cabeças:255 Setores por trilha:63 Cilindros:627 +----------------------------------------------------------------------------- +Nome Opções Tipo Part. Tipo Sist. Arquivos [VOLUME] Tamanho(MB) +hda1 Boot Primary Win 95 FAT 32 1953.12 +hda5 Logical DOS FAT 16 (BIG) GLEYDSON 172.58 + Pri/Log Espaço Livre 2910.55 + + + + + + + + + +Enter the number of Cylinders: 627 + +---------------------------------------------------------------------------- +O valor que aparece ao selecionar a opção, é o valor que o disco esta +utilizando atualmente(cilindros), e será pedido que digite um valor para os +Cilindros, que substituirá os da BIOS durante a seção de particionamento. +Para sair desta tela sem alterar o valor, pressione . A mesma tela e +explicação se aplicam para as alterações de Cabeças e Setores. + +OBS: Se por acaso digitar um valor incorretamente para o tamanho do disco e + não se lembrar mais do valor antigo ou original, selecione a opção Done, e + tecle para sair do CFdisk sem gravar as alterações feitas para o + disco, pois se continuar a utilizar o CFdisk com o tamanho do disco + incorreto, os dados existentes nele e até mesmo partições poderão ser + perdidos(as). + +Se aumentar o tamanho do disco, setores adicionais são acrescentados no +final do disco, e são mostrados como espaço livre. +Se diminuir o tamanho do disco, as partições que estavam localizadas após +o setor/cilindro que foi excluido(se existir alguma), será apagada e a +última partição(ou espaço livre ao final do disco rígido), terá seu +tamanho alterado e terminará neste "novo" último setor do disco. + + + +2.3.6-) O comando Help ou + +O comando Help mostra a tela de ajuda do programa, que descreve as funções +das teclas utilizadas pelo programa e suas funções. + + + +2.3.7-) O comando Maximize + +Este comando aumenta a utilização de espaço do disco na partição atual. +Isto porque o DOS, OS/2 e outros sistemas operacionais utilizam o primeiro +setor da primeira trilha da partição do disco e em todas as partições Lógicas +para iniciar o sistema operacional, utilizando a segunda trilha em diante +daquela partição para fazer o armazenamento de arquivos. Este espaço perdido +entre o segundo e o último Setor da primeira trilha da primeira cabeça, pode +ser recuperado com a utilizando este comando. + +Este comando faz com que a partição se torne imcompatível com DOS, OS/2 +e outros Sistemas Operacionais que utilizam este primeiro Setor do disco +para iniciar o sistema operacional. + +Se este comando for utilizado, será colocada uma opção chamada NC(não +compatível) em Flags(na tela principal do CFdisk). + +Esta opção faz o uso máximo do disco e a incompatibilidade com o DOS/OS/2, +etc. O padrão quando criando uma Partição, é criando Partições compativeis +com o DOS, OS/2, etc. + +OBS: O Fdisk(8) e partições formatadas com o sistema de arquivos FAT32, fazem + a utilização completa deste espaço entre o segundo e o último Setor da + primeira trilha do disco, eliminando o desperdício de espaço. + + + +2.3.8-) O comando New + +O comando New, cria uma nova partição usando o espaço livre(FreeSpace) +existente no disco. Após escolher esta opção, o CFdisk perguntará se deseja +criar uma partição Primária, Lógica ou Cancelar o comando. + +Escolhendo criar uma partição Primária ou Lógica, o sistema perguntará o +tamanho da partição que deseja criar, por padrão, o CFdisk mostrará o espaço +livre total disponível no disco para a criação da nova partição(em MegaBytes). +Tecle para criar uma partição do tipo escolhido com este tamanho ou +digite um tamamho menor. O CFdisk permite que seja digitados valores em: + +- MegaBytes(M - o padrão do programa) +- KiloBytes(K) +- Cilindros(C) +- Setores(S) + +Digitando-se o tamanho da partição seguida de uma das letras acima. Se a +letra não for digitada, o programa assumirá o tamanho que digitou em MegaBytes. + +OBS1: Quando criar uma partição Lógica, automaticamente será criada uma + partição extendida, entre hdx1 e hdx4, e a partição Extendida não é + mostrada na tela de particionamento de disco. Se desejar exibir a + partição extendida, execute o comando PRINT

e escolha a opção + Sector para verificar qual é a identificação da partição Extendida + no disco. Para maiores detalhes, veja o comando PRINT

. + +OBS2: São permitidas, no máximo, 4 partições Primárias e Extendidas(3 Primárias + e 1 Extendida ou 4 partições Primárias em cada disco). O CFdisk + calculará automaticamente os valores das partições lógicas caso + as primeiras 4 partições forem ocupadas. + +O próximo passo, é a localização da partição no espaço livre existente no +disco. As duas opções disponíveis são: + +- Beginning : A partição é colocada a partir do inicio do espaço livre no + disco, ocupando o espaço livre de acordo com o seu tamanho + (do início para o fim do espaço livre ), este é o padrão para + a criação de novas partições e o mais utilizado. Veja o exemplo, + a criação de uma partição de 30MB em um disco com 50MB de + espaço não particionado, sendo que este disco já possui uma + partição de 120MB(com espaço total de 170MB) + + ##################################MMMMMMMMMMMMMMMMMMMMMMMMMM + | | + Partição existente(120MB) Espaço Livre(50MB) + + + com a nova partição criada: + + ###################################################MMMMMMMMM + | | | + Partição existente(120MB) Nova partição Espaço + (30MB) Livre + +- End : A partição é criada subtraindo-se o espaço livre total do disco + pelo tamanho da partição que será criada, começando a criar + esta partição a partir do ponto que resultou esta subtração. + Veja abaixo no exemplo, a partição que será criada terá o + tamanho de 30MB e existe no disco um espaço não particionado + de 50MB, com 120MB já ocupados por uma partição existente: + + ##################################MMMMMMMMMMMMMMMMMMMMMMMMMM + | | + Partição existente(120MB) Espaço Livre(50MB) + + + com a nova partição criada (Selecionando a opção End): + + ##################################MMMMMMMMMM################# + | | | + Partição existente(120MB) Espaço Nova partição + Livre (30MB) + + A partição que será criada utilizara o espaço livre entre o + último Setor do disco e o setor resultante da subtração(170MB-30MB). + Mesmo assim, a ordem que será criada esta partição partição + será criada do Setor inicial(que é o resultado da subtração) + para o último Setor do disco. Existirá um espaço livre de 20MB + entre a primeira partição (de 120MB) e a nova partição de 30MB. + + + +2.3.9-) O comando Print

+ +Este comando mostra a tabela de partição no formato selecionado na tela, +ou permite que seja gravado um arquivo no disco. Todas as partições são +classificadas na ordem que foram gravadas no disco. + +Os formatos aceitos para visualização de partições são: + +RAW : Formato de dados do disco, mostra os setores que serão gravados + para o disco, caso seja escolhido o comando WRITE . O formato + mostrado é exatamente aquele que será gravado para ao disco. + Abaixo um exemplo deste formato: + -------------------------------------------------------------------- + Disk Drive: /dev/hda + Sector 0: + 0x000: EB 69 4C 49 4C 4F 01 00 14 00 D7 02 00 00 00 00 + 0x010: FB 1B CF 36 74 D8 80 23 01 75 D8 80 23 01 73 D8 + 0x020: 80 23 01 01 77 01 77 D8 80 23 01 78 D8 80 23 01 + 0x030: 64 D8 80 23 01 65 D8 80 23 01 66 D8 80 23 01 67 + 0x040: D8 80 23 01 68 D8 80 23 01 69 D8 80 23 01 6A D8 + 0x050: 80 23 01 6B D8 80 23 01 00 00 00 00 00 00 00 00 + 0x060: 00 00 00 00 00 00 00 00 00 00 00 B8 C0 07 8E D8 + 0x070: 8C 06 66 00 89 36 64 00 89 1E 68 00 88 16 6A 00 + 0x080: B8 00 9A 8E C0 B9 00 01 29 F6 29 FF FC F3 A5 EA + 0x090: 94 00 00 9A FA 8E D8 8E C0 BC 00 B0 B8 00 90 8E + 0x0A0: D0 FB B0 0D E8 57 00 B0 0A E8 52 00 B0 4C E8 4D + 0x0B0: 00 BE 30 00 BB 00 10 FC AD 89 C1 AD 89 C2 09 C8 + 0x0C0: 74 20 46 E8 43 00 72 06 81 C3 00 02 EB EA 50 B0 + 0x0D0: 20 E8 2A 00 58 88 E0 E8 12 00 31 C0 88 C2 CD 13 + 0x0E0: EB CF B0 49 E8 17 00 EA 00 00 00 9B 50 C0 E8 04 + 0x0F0: E8 01 00 58 24 0F 04 30 3C 3A 72 02 04 07 30 FF + 0x100: B4 0E CD 10 C3 5A 59 5B C3 F6 C2 40 74 52 80 E2 + 0x110: BF 53 51 52 B4 08 CD 13 72 EB 88 F3 5A 88 16 6D + 0x120: 01 88 F2 30 F6 88 F7 58 51 86 CD D0 C5 D0 C5 80 + 0x130: E5 03 89 0E 6B 01 59 83 E1 3F F7 F1 FE C2 88 16 + 0x140: 6E 01 31 D2 43 F7 F3 88 D6 8A 16 6D 01 3B 06 6B + 0x150: 01 77 13 86 C4 D0 C8 D0 C8 0A 06 6E 01 89 C1 5B + 0x160: B8 01 02 CD 13 C3 5B 31 C0 F9 C3 00 00 00 00 00 + 0x170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 01 + 0x1C0: 01 00 0B FE 3F 8F 3F 00 00 00 51 4C 23 00 00 00 + 0x1D0: 41 D7 83 FE BF 6F 17 75 73 00 59 81 25 00 00 00 + 0x1E0: 01 98 05 FE 7F D6 98 42 25 00 7F 32 4E 00 00 00 + 0x1F0: 81 70 82 FE BF 72 70 F6 98 00 43 BC 00 00 55 AA + + Sector 2441880: + 0x000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 + 0x1C0: 01 98 0B FE 7F D6 3F 00 00 00 40 32 4E 00 00 00 + 0x1D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA + ----------------------------------------------------------------- + A primeira tabela de partição mostrada é a Primária, depois + as tabelas de partições ligadas com cada partição lógica. Como + no exemplo, os dados são mostrados em bytes Hexadecimais(na + primeira coluna) seguidos de 16 bytes por linha. + +Sector : Mostra a tabela de partição classificada por setores. Esta + opção mostra o espaço não particionado no disco e a partição + Extendida, que é mostrada antes das partições Lógicas. + Abaixo um exemplo deste formato: + ------------------------------------------------------------------ + Partition Table for /dev/hda + + First Last + # Type Sector Sector Offset Length Filesystem Type (ID) Flags + -- ------- -------- --------- ------ --------- ---------------------- --------- + 1 Primary 0 2313359 63 2313360 Win95 FAT32 (0B) Boot (80) + Logical 2313360 2441879 0 128520 Free Space None (00) + 3 Primary 2441880 7566614 0 5124735 Extended (05) None (00) + 5 Logical 2441880 7566614 63 5124735 Win95 FAT32 (0B) None (00) + 2 Primary 7566615 10024559 0 2457945 Linux (83) None (00) + 4 Primary 10024560 10072754 0 48195 Linux Swap (82) None (00) + ------------------------------------------------------------------ + + onde: + # - Identificação da partição no disco /dev/hda + Type - Tipo da partição(veja o exemplo) + First Sector - Primeiro Setor utilizado para o armazanamento da partição. + Last Sector - Último Setor utilizado para o armazenamento da partição. + Offset - + Lenght - Tamanho total da partição em setores (Last Sector - First + Sector). + FileSystem Type (ID) - Identificação do Sistema de Arquivos da partição, + seguido do seu código hexadecimal no CFDisk. A partição + Extendida é identificada como um sistema de arquivos + com o código 05 (veja o exemplo). + Flags - Opções da partição seguido de seu valor em + hexadecimal. + +Table : Mostra a tabela de partição classificada pelo número da partição. + Esta opção deixa fora todo espaço livre e não usado na partição. + Abaixo um exemplo deste formato. + ---------------------------------------------------------------- + Partition Table for /dev/hda + + ---Starting--- ----Ending---- Start Number of + # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors + -- ----- ---- ---- ---- ---- ---- ---- ---- -------- --------- + 1 0x80 1 1 0 0x0B 254 63 143 63 2313297 + 2 0x00 0 1 471 0x83 254 63 623 7566615 2457945 + 3 0x00 0 1 152 0x05 254 63 470 2441880 5124735 + 4 0x00 0 1 624 0x82 254 63 626 10024560 48195 + 5 0x00 1 1 152 0x0B 254 63 470 63 5124672 + --------------------------------------------------------------- + + onde: + # - Número da partição de disco + Flags - As opções utilizadas com a partição (em + valor Hexadecimal). + O valor 0x80 equivale a BOOT. + O valor 0x00 equivale a nenhuma opção + utilizada naquela partição. + Starting + Head - Cabeçote Inicial + Sector - Setor Inicial + Cyl - Cilindro Inicial + ID - Identificação do Sistema de arquivos(em + hexadecimal, conforme a tabela do CFdisk). + Ending + Head - Cabeçote Final + Sector - Setor Final + Cyl - Cilindro Final + Start Sector - Setor inicial da partição + Number of Sectors - Número de setores ocupados pela partição. + +Se a partição não inicia ou não termina em um cilindro limite do disco +ou se o seu tamanho não é divisível pelo tamanho do cilindro, um * é será +mostrado após o setor não alinhado. Este problema normalmente ocorre quando +a partição é criada por um Sistema operacional em que o limite da partição +não é alinhada com o cilindro ou que utiliza a contagem do tamanho do disco +de forma diferente. + + A tabela de partição somente tem 10 bits disponível para identificar o +cilindro inicial e final. Assim, quando o setor inicial absoluto é um +cilindro maior que 1023(final do disco), o valor máximo para a cabeça +inicial, setor e cilindro são mostrados. Este metodo é usado pelo OS/2, e +e corrige os problemas associados com OS/2 caso o Fdisk regrava a tabela de +partição quanto ela não esta neste formato. + +Desde então Linux e OS/2 utilizam esta contagem de setores absolutos, os +valores na cabeça inicial e final, Setor e Cilindro não são usadas. + + + +2.3.10-) O comando quit + +Esta opção faz com que o CFdisk abandonar todas as alterações e +retornar para o Aviso de comando. Quando esta opção é escolhida, o programa +retorna deixando o disco como estava antes de se iniciar o particionamento. + +Se escolher esta opção o CFdisk abandonará o particionamento de disco +e voltará para a linha de comandos imediatamente. Se alterar/criar/excluir +alguma partição de disco e escolher esta opção, o programa emitirá um Beep +indicando que alguma alteração feita no disco foi abandonada. + +OBS: Esta opção é útil caso tenha se cometido algum engano durante o + particionamento do disco, como apagar por uma partição que contém + arquivos, alterar o tamanho do disco(geometria), etc. Lembre-se que + tudo o que fez será abandonado, durante o particionamento, se escolher + esta opção. + + + +2.3.11-) O comando type + +Comando usado para alterar o tipo do sistema de arquivos utilizado +pela partição. As partições, quando criadas, recebem o sistema de arquivos +Linux Native(ou simplesmente Linux - tipo 83). O CFdisk pode criar, manipular, +excluir, uma grande variedade de Sistemas de arquivos para os mais diversos +tipos de sistemas operacionais existentes, veja o final deste manual para +ver as partições compatíveis com este programa. + +Para alterar o tipo do sistema de arquivos (File System) utilizado pela +partição, tecle , e digite o valor de acordo com a lista de partições +disponíveis no programa. + +Por exemplo, para mudar a partição do tipo Linux para Linux Swap, selecione +esta partição, e tecle , e digite o número 82(que corresponde a Linux +Native) e tecle , e a partição terá seu sistema de arquivos alterado. + + + +2.3.12-) O comando units + +A função deste comando é alterar as unidades de medida do tamanho da +partição que é mostrado na tela, por padrão, ele é mostrado em MegaBytes. +As unidades de medida do tamanho da partição são em MegaBytes, Cilindros e +Setores ocupados pela partição de disco. +Abaixo um exemplo da mudança da unidade de medida para Cilindros. +---------------------------------------------------------------------------- + CFdisk 0.8l + + Disk Drive: /dev/hda + Heads:255 Sectores per track:63 Cylinders:627 +----------------------------------------------------------------------------- +Name Flags Part Type FSType [LABEL] Cilinders +hda1 Boot Primary Win 95 FAT 32 249 +hda5 Logical DOS FAT 16 (BIG) GLEYDSON 22 + Pri/Log Free Space 371 + + + + + + + + + + +[Bootable] [Delete] [Help] [Maximize] [Print] +[Quit] [Type] [Units] [Write] +---------------------------------------------------------------------------- +Será mostrada a quantidade de cilindros que a partição ocupa no disco ao +invés do espaço em MB. + + + +2.3.13-) O comando Write + +Este comando grava todas as tabelas de partições criadas/modificadas e +excluidas para o disco. Só é aceita a tecla em maiúscula para gravação +da partição de disco, por motivos de segurança para que não seja feita a +gravação acidental das partições enquando estiver utilizando o programa. +Para quem utiliza as setas do teclado, o método é o mesmo que as outras +opções. + +Após selecionar esta opção, o CFdisk perguntará se confirma a gravação +das partições para o disco. + +Para gravar a partição, digite "yes" e tecle . +Para cancelar o comando, pressione ou digite "no" e tecle . + +Após confirmar com "yes", o CFdisk gravará a tabela de partição no disco +e fara o Kernel re-ler a tabela de partição do disco, para se evitar +reiniciar o sistema para utilizar a nova tabela de partição. + +A tentativa de re-leitura da tabela de partição pode falhar. Para +solucionar este problema, é preciso reiniciar o computador, quando o +computador é reiniciado, o sistema operacional faz uma nova leitura das +tabelas de partições existentes no disco, fazendo com que sejam reconhecidas +corretamente. + + + +3-) Tipos de partições compatíveis com o CFdisk + +Abaixo uma listagem das partições compatíveis com o programa CFdisk e +seus respectivos códigos Hexadecimais, para consulta técnica ou utilização +durante o particionamento de disco. + +Código Nome +01 - DOS FAT12 +02 - Xenix root +03 - Xenix usr +04 - DOS FAT16 (<32MB) +05 - Extendida +06 - DOS FAT16 (>=32MB) +07 - OS/2 HPFS ou NTFS +08 - AIX +09 - AIX inicializável +0A - OS/2 Boot Manager +0B - Windows 95 FAT32 +0C - Windows 95 FAT32(LBA) +0E - Windows 95 FAT16(LBA) +0F - Windows 95 Extendida +11 - DOS FAT12 oculta +12 - DOS FAT16 oculta +16 - DOS FAT16 oculta +17 - HPFS OS/2 oculta +40 - Venix 80286 +51 - Novell +52 - Microport +63 - GNU Hurd +64 - Novell Netware 286 +65 - Novell Netware 386 +75 - PC/IX +80 - Minix Antigo +81 - Linux / Minix +82 - Linux Swap +83 - Linux Nativa +85 - Linux Extendida +93 - Amoeba +94 - Amoeba BBT +A5 - BSD/386 +A6 - Open BSD +A7 - NextStep +B7 - BSDI Sistema de Arquivos +B8 - BSDI Swap +C7 - Syrinx +DB - CP/M +E1 - DOS access +E3 - DOS R/O +F2 - DOS secundária +FF - BBT + + + + +4- ) Direitos Autorais + +Este documento foi desenvolvido com base em minha experiência e conhecimento em +discos e partições, e mediante pesquisa em alguns documentos como os How-TO do +Linux tendo como objetivo a contribuição para a comunidade Linux em geral. + +Gleydson M. da Silva (gleydson_s@yahoo.com ou gleydson@linuxbr.com.br) + +Qualquer dúvida, sugestão ou reclamação podem ser mandadas para um dos +E-Mail's Acima. Conto com sua contribuição para a melhoria deste Manual. + +Autorizo a reprodução Total ou parcial deste texto para que seja utilizado para +fins educativos, autoaprendizado, colocação em Home pages e qualquer outra +forma de distribuição não comercial do documento desde que sejam mantidos os +meus créditos pela pesquisa e desenvolvimento deste documento de acordo com os +termos da GNU (veja abaixo). + + + + +5- ) Licenças e Garantias sobre este documento + + +CFdisk-Portuguese Copyright (C) 1999 Gleydson M. da Silva +  +Este é um documento de livre distribuição, que pode ser copiado e +distribuído sob os termos da Licença Pública Geral  GNU, conforme publicada +pela Free Software Foundation, versão 2 da licença ou (a critério do autor) +qualquer versão posterior. + +Este documento é distribuído com a itenção de ser útil ao seu utilizador, +no entanto NÃO TEM NENHUMA GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS +OU DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença Pública +Geral  GNU para maiores detalhes. + +gleydson_s@yahoo.com +gleydson@linuxbr.com.br + + + +6- )Nota sobre Marcas Registradas + +Os programas mencionados neste manual são de propriedade dos seus respectivos +donos: + +MS-DOS, Windows 3.1x, Windows 9x, Windows NT são de propriedade da Microsoft. +OS/2 e OS/2 Warp são de propriedade da IBM + + +7- ) Agradecimentos + +Agradeço a todas as pessoas que me mandam correções, comentários, críticas, +elogios, dúvidas sobre este documento, pois através destas mensagens, estão +contribuindo para a melhoria deste projeto e me icentivando em sua continuação. + + +Agradecimentos especiais a: + +Eduardo Marcel Macan - Pelo apoio e interesse na + divulgação deste projeto e outros documentos relacionados com a + tradução e divulgação de documentos sobre o Linux no Brasil. + +Jorge Godoy - Pela revisão deste documento e primeiras + orientações para a conversão deste para SGML. + +Adam di Carlo - Que me deu apoio na colocação deste documento + na documentação da distribuição Debian. + +E a voce pelo interesse em conhecer mais sobre o Linux. + + + \ No newline at end of file diff --git a/fdisk/doc/Fdisk-Portuguese.html b/fdisk/doc/Fdisk-Portuguese.html new file mode 100644 index 00000000..fdf29b80 --- /dev/null +++ b/fdisk/doc/Fdisk-Portuguese.html @@ -0,0 +1,1118 @@ + + + + + + + Fdisk-Portugues-HOWTO + + + +

Fdisk-Portugues-HOWTO Copyright (C) 1999 Gleydson +M. da Silva +
  +
  +
  +
  +
  +
  +
  +

+


+
Gleydson M. da Silva - gleydson@linuxbr.com.br +
Versão 1.3
+ +
+
  +
  +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Índice

+ +

1 - Introdução +ao Fdisk +
  1.1 - O que é uma Partição +de Disco +
  1.2 - A Tabela de Partição +
  1.3 - Introdução ao Particionamento +de discos +
  1.4 - Identificações utilizadas +neste documento +
  1.5 - Identificação de discos +e partições no Linux +
  1.6 - Tipos de partições +de disco +
  1.7-) Observações sobre +o formato DOS 6.XX(FAT 16) +

2 - Iniciando o programa Fdisk +
  2.1 - Opções de Linha de +comando +
  2.2 - Comandos do Fdisk +

3 - Manipulando partições +no disco rígido +
  3.1 - Listando partições +existentes no disco +
  3.2 - Criando partições +de disco +
  3.3 - Mudando o tipo da partição +
  3.4 - Excluindo uma partição +de disco +
  3.5 - Gravando partições +alteradas para o disco +
  3.6 - Abandonando o programa sem gravar +alterações para o disco +
  3.7 - Alternando entre partição +inicializável/não inicializável +
  3.8 - Escolhendo a unidade  para +mostrar o tamanho ocupado pela partição +

4 - Tipos de partições +reconhecidas pelo Fdisk +

5 - Direitos Autorais +

6 - Licenças e Garantias +sobre este documento +

7 - Marcas Registradas +

8 - Agradecimentos +
  +
  +
+
+
+
+
+
+
+
+
+
+
+
+

+

1-) Introdução ao Fdisk

+ +

    Fdisk é um programa utilizado para o particionamento +de discos rígidos IDE e SCSI.   A versão +do programa Fdisk descrita neste manual é a 2.8 +

ATENÇÃO: ESTE MANUAL TEM COMO OBJETIVO A EXPLICAÇÃO +DE +
                     +FUNCIONAMENTO E  UTILIZAÇÃO DO FDISK DO LINUX (NÃO +O +
                     +FDISK DO DOS), MESMO QUE  VOCE SEJA UM USUÁRIO DO DOS, +
                     +RECOMENDO QUE LEIA ESTE MANUAL COMO UMA REFERÊNCIA +
                     +TÉCNICA E PARA SEU APRENDIZADO. +

    Este documento é distribuído com +a itenção de ser útil ao seu utilizador, no entanto +NÃO TEM NENHUMA GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS +, COMERCIAIS OU DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a +Licença Pública Geral  (GNU) para maiores detalhes. +

+ +
  +
+

1.1-) Partição de Disco

+ +

    Uma partição de disco é +o local onde o sistema operacional armazena seu sistema de arquivos(arquivos, +diretórios, FAT, boot sector, etc). +

+ +
  +
+

1.2-) Tabela de partição

+ +

    A Tabela de partição é +o local do disco rígido onde se localizam os dados sobre todas as +partições existentes no disco como o sistema de arquivos +utilizado, se ela é inicializável, a cabeça inicial/final, +setor inicial/final, cilindro inicial/final, número de setores ocupados +por ela no disco. +

+ +
  +
+

1.3-) Introdução ao +particionamento de discos

+ +

    Particionar o disco rígido é dividir +ele em partes para armazenamento de arquivos e programas. As partições +criadas no disco podem ter o tamanho que desejar (desde que esteja dentro +da capacidade máxima do disco rígido). +
     Uma partição não interfere +em outras partições do mesmo disco(é como se tivessemos +vários discos rígidos dentro de um). +
    Em um disco rígido, pode ser criada uma partição +única, que neste caso todo o disco rígido  é +usado para armazenar os arquivos(que é o caso mais comum caso voce +tenha o DOS), ou várias partições, que podem ser usadas +pelo mesmo SO(Sistema Operacional) ou outros sistemas operacionais diferentes(um +exemplo de várias partições, é se voce for +usar o DOS e o Linux no mesmo disco, os dois +
sistemas vão estar no mesmo disco mas um não interfere +no outro). +
    Este manual tem a itenção de explicar +o funcionamento do programa fdisk (fdisk do Linux não do DOS!). +

+ +
  +
+

1.4-) Algumas identificações +utilizadas neste manual para facilitar a  compreensão do texto

+ +

    Esta parte descreve algumas características +de organização deste manual e algumas identificações +que adotei para facilitar o seu entendimento, e as explicações +que serão dadas. +

    Explicação de nomes e comandos, será +seguida da palavra "onde" e abaixo dela as explicações +sobre os comandos, exemplo: +

onde: +
nome a ser explicado1  : Descrição +
nome a ser explicado2  : Descrição +
nome a ser explicado3  : Descrição +

ou +

onde: +
nome a ser explicado1  - Descrição +
nome a ser explicado2  - Descrição +
nome a ser explicado3  - Descrição +
  +

    Quando for feita alguma referência com tecla +do teclado, por exemplo, pressione p para listar as partições, +a letra sera colocada entre <> para facilitar a interpretação: +
pressione <p> para listar as partições +
após isto pressione <Enter> para confirmar +
pressione <l> para listar os tipos de partições disponíveis +
  +

    As linhas pontilhadas que aparecem na tela, veja +abaixo, +
---------------------------------------------------------------------------- +
---------------------------------------------------------------------------- +
servem para identificar que o que esta entre as linhas é um +exemplo de como +
será a resposta do comando para a tela de seu computador. +

+ +
  +
+

1.5-) Identificação +de discos e partições no Linux

+ +

    Antes de descrever como se utiliza o programa fdisk, +é importante fazer algumas explicações sobre a identificação +das partições e unidades de disco no sistema Linux( e outros +*nix). Se voce for um usuário que já conhece a interpretação +de discos e partições neste sistema, voce não precisará +ler esta parte. +
    No sistema operacional Linux, os dispositivos existentes +no computador (como impressoras, unidades de disquetes, discos rígidos, +monitor, placa de som, etc...) são identificados por um nome referente +a este dispositivo e colocado no diretório /dev (que é utilizado +para identificar dispositivos ou periféricos existentes no computador). +
   A identificação dos discos rígidos +segue a seguinte forma: +

  /dev/hda1 +
  |       |   |  +| +
  |       |   |  +|_Número que identifica a partição do disco rígido(1=Primeira, +2=segunda) +
  |       |   | +
  |       |   |_Letra +que identifica o disco rígido(a=primeiro disco, b=segundo disco, +etc..) +
  |       | +
  |       |_Sigla HD - Significa +que é um disco rígido IDE(Se tiver um SD significa SCSI) +
  | +
  |_ Identificação do diretório onde os dispositivos +do sistema são armazenados +

OBS: As unidades de disco rígido SCSI, são +identificadas com as letras sd  seguida pela letra da +
         unidade e número +da partição e os discos IDE são identificados +por hd seguida pela letra da +
         unidade de disco e +o número da partição do disco(como visto acima). +

Abaixo, algumas identificações de disco do sistema Linux: +

/dev/hda1    -   Disco rígido +IDE primário principal - Primeira partição +
/dev/hda2    -   Disco rígido +IDE primário principal - Segunda partição +
/dev/hda3    -   Disco rígido +IDE primário principal - Terceira partição +
/dev/hdb1    -   Disco rígido +IDE primário escravo - Primeira partição +
/dev/hdb2    -   Disco rígido +IDE primário escravo - Segunda partição +
/dev/hdb3    -   Disco rígido +IDE primário escravo - Terceira partição +
/dev/hdc1    -   Disco rígido +IDE secundário principal - Primeira partição +
/dev/hdc2    -   Disco rígido +IDE secundário principal - Segunda partição +
/dev/hdc3    -   Disco rígido +IDE secundário principal - Terceira partição +
/dev/hdd1    -   Disco rígido +IDE secundário escravo - Primeira partição +
/dev/hdd2    -   Disco rígido +IDE secundário escravo - Segunda partição +
/dev/hdd3    -   Disco rígido +IDE secundário escravo - Terceira partição +
/dev/sda1    -   Primeiro disco rígido +SCSI - Primeira partição +
/dev/sda2   -   Primeiro disco rígido +SCSI - Segunda partição +
/dev/sda3    -   Primeiro disco rígido +SCSI - Terceira partição +
/dev/sdb1    -   Segundo disco rígido +SCSI - Primeira partição +
/dev/sdb2    -   Segundo disco rígido +SCSI - Segunda partição +
/dev/sdb3    -   Segundo disco rígido +SCSI - Terceira partição +

    No exemplo acima foram usadas 3 partições +por disco, mas podem existir mais partições no mesmo disco, +um exemplo é se o disco rígido possuir partições +Lógicas, que são identificadas no sistemas a partir de +/dev/hdx5 em diante. +

    Abaixo um exemplo de como o Linux identifica as partições +em cada disco existente em seu computador: +

Vamos supor que eu tenha 2 discos rígidos: +
o 1ºdisco de 2GB e o 2ºdisco  de 1GB (Giga +Byte ou 1.000 Megas) +

    No primeiro disco(de 2GB), a primeira partição +é de 800MB do tipo FAT16(DOS), a segunda partição +é de 1.2GB do tipo EXT2(Linux)(1.2GB+800MB=2GB +que é a capacidade total do disco). Então as partições +seriam identificadas da seguinte forma no Linux: +

/dev/hda - Disco rígido Primário Principal +
/dev/hda1 - Primeira partição do primeiro disco +rígido (de 800MB do tipo DOS) +
/dev/hda2 - Segunda partição do primeiro disco +rígido( de 1.2GB do tipo Linux) +

    Neste caso estariam disponíveis 800MB +para serem usados com o DOS e 1.2GB para o Linux. +
    Por exemplo, se voce particionar um disco rígido +em duas partes e usar as duas partições no DOS, ele reconhecerá +as partições como sendo C: e D:. +

Lembre-se: Quando um disco é particionado, uma partição +não interfere nas outras, repare que +
                    +quando voce particiona(divide) um disco, é como se tivesse dois +discos rígidos(o +
                    +único cuidado que voce deve tomar é com as cópias +de segurança, porque se der um +
                    +problema de parte eletrônica no disco rígido, por exemplo,  +a sua placa controladora +
                    +queimar ou o cabeçote dele ir pro espaço, serão perdidas +as suas 2 partições que +
                    +estão armazenadas nele. +
  +

Voltando ao exemplo das classificações das partições +do disco, vamos para o segundo disco: +

    No segundo disco(1GB), eu tenho uma partição +de 950MB do tipo FAT16(DOS), que costumo usar para armazenar +arquivos temporários e cópias de segurança de meu +computador, etc..., e outra de 50MB SWAP(Partição +de memória virtual como descrevi acima)(950MB+50MB=1GB). +Então as partições deste disco seriam identificadas +da seguinte forma no Linux: +

/dev/hdb   - Disco rígido principal escravo +
/dev/hdb1 - Primeira partição do disco acima ( +de 950MB do tipo DOS) +
/dev/hdb2 - Segunda partição do disco acima ( +de 50MB do tipo SWAP) +

    No disco acima, 950MB estão disponíveis +para serem usados pelo DOS e 50 MB pela memória virtual (SWAP) +do Linux. +

    Note que se voce utiliza o MS-DOS, não será +possível conseguirá ver as partições do Linux +e SWAP, porque são imcompatíveis com o formato aceito pelo +DOS (ele identificaria a primeira partição do primeiro disco(800MB) +como a unidade C: e a primeira partição do segundo disco(950MB) +como unidade D), mas o contrário não acontece; O Linux tem +total compatibilidade com a partição DOS FAT12, FAT16, FAT32, +OS/2 HPFS, e muitas outras. +

+ +
  +
+

1.6-) Tipos de partições +de discos

+ +

   As partições de disco são divididas +em tres tipos: Primária, Extendida e Lógica. +

   Pode se ter no máximo quatro partições +primárias e extendidas no mesmo disco. A partição +Primária permite o armazenamento de arquivos e diretórios. +
Todos os computadores que possuem somente a unidade C(supondo que voce +use o DOS), usam este tipo de partição para armazenamento +de arquivos e inicialização do sistema operacional. +
    Se for preciso criar mais que 4 partições +no mesmo disco, será necessário +
criar uma partição Extendida. A partição +Extendida  não pode ser utilizada para armazenar arquivos. +Ela é usada para a criação de outras partições, +dentro dela, que são chamadas de partições Lógicas. +
    Uma partição extendida podem +conter várias partições Lógicas. As +partições Lógicas podem armazenar arquivos e diretórios(como +as partições primárias). +
    Um mesmo disco rígido pode armazenar mais +de 64 partições independentes uma das outras. +

OBS: Os arquivos e diretórios podem ser armazenados somente +em partições de disco Primárias ou Lógicas, +a partição Extendida não é usada para +armazanamento de arquivos e diretórios. +

     Se possuir duas partições em +seu computador (C: e D: no DOS), e não estiver usando a partição +D:, a instalação pode ser feita nesta partição +desde que ela tenha o espaço necessário para o sistema operacional +Linux, os programas que desejar instalar, mais a partição +SWAP. +

+ +
  +
+

1.7-) Observações sobre +o formato DOS 6.XX(FAT 16)

+ +

     No formato DOS 6.XX(FAT16), o primeiro +setor da área de dados da partição é utilizado +frequentemente pelo DOS para armazenamento de dados sobre a partição +de disco, e estes dados são usados pelo sistema para se ter maior +confiabilidade do que os dados armazenados na tabela de partição. +O sistema de arquivos DOS, faz o FDISK(do DOS) limpar os primeiros +512 bytes da área de dados da partição sempre que +uma mudança de tamanho acontecer. +
     O formatador do DOS(format) verifica +este primeiro setor toda vez que a upção /U (que é +utilizada para não salvar dados para se fazer a desformatação +do disco) é utilizada. +
     Isto é considerado uma FALHA no Format(do +DOS) +e no Fdisk(do DOS). +
A opção abaixo deve ser utilizada caso voce crie uma +partição do DOS FAT16 com o Fdisk, que faz com que +os primeiros 512 bytes daquela partição sejam "limpos", para +manter a compatibilidade com o DOS. Utilize esta opção dentro +do Linux, após criar a partição com o Fdisk e reiniciar +o seu +
computador. Foi notado que esta opção só funciona +corretamente somente quando o Sistema Linux estiver instalado em seu computador. +Não me responsabilizo caso utiliza-la a partir de um disquete de +recuperação. +

dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 +

onde: +
hdx1 - É a identificação da unidade de +disco e a partição que foi criada  pelo Fdisk utilizando +o sistema de arquivos DOS que terá seu  primeiro setor "limpo". +

OBS1: Cuidado ao utilizar esta opção, um pequeno +descuido pode resultar na  perda de dados do +
            +seu disco rígido ou outras partição. +
OBS2: Não utilize este comando com partições +que utilizam o sistema de arquivos  FAT32 +
            +(utilizada nos sistemas operacionais Windows 95 OSR/2 e superiores) +se for utilizada em +
            +um disco com este sistema, sua FAT será corrompida,  se isto +acontecer, será necessária a +
            +re-formatação da partição. +
OBS3: É extremamente recomendado que se utilize o programa +de particionamento que +
            +acompanha o seu sistema operacional para a criação da partição. +Por exemplo, se deseja +
            +criar uma partição DOS 6.XX, utilize o FDisk qua acompanha +o DOS. +

+ +
  +
+

2-) Iniciando o programa Fdisk

+ +

Para iniciar o programa fdisk(Linux)digite: +

fdisk [unidade] +

Onde: +
unidade - deve ser a unidade de disco rígido no padrão +Linux( /dev/hda,  /dev/hdb, /dev/sda, +
                +/dev/sdb, etc... ). Se voce tem apenas 1  disco rígido +IDE, use /dev/hda, para fazer o +
                +fdisk trabalhar com este disco ou digite fdisk sem especificar a unidade. +Se possuir 1 +
                +disco SCSI, use /dev/sda +

  Se unidade não for especificada, o programa fdisk usará +/dev/hda +como unidade de disco padrão. +

ATENÇÃO : A OPERAÇÃO DE PARTICIONAMENTO +DE DISCOS PODE FAZER COM +
                     +QUE OS DADOS  ARMAZENADOS EM SEU DISCO RÍGIDO SEJAM +
                     +PERDIDOS, SE FOR USADA INCORRETAMENTE. É SEMPRE +
                     +RECOMENDADO RETIRAR UMA CÓPIA DE SEGURANÇA DOS SEUS +
                     +ARQUIVOS EXISTENTES NO MICRO ANTES DE SE EXECUTAR UM +
                     +PROGRAMA DESTE TIPO, A NÃO SER QUE TENHA CONFIANÇA NO +
                     +QUE ESTA FAZENDO E QUE ENTENDEU AS EXPLICAÇÕES SOBRE A +
                     +IDENTIFICAÇÃO DE   DISCOS RÍGIDOS E SUAS +PARTIÇÕES NO +
                     +SISTEMA. +

+ +
  +
+

2.1-) Opções de linha +de comando

+ +

   Com a utilização de opções +de linha de comando, voce pode fazer com que o programa inicie de uma forma +específica, ou personalizada. +

fdisk [-b] [-u] [unidade]   - +Opções aceitas para o particionamento. +
fdisk [-l] [-b] [-u]             +- Opções aceitas para listar as partições atuais. +
fdisk [-s] [unidade]          +- Opção aceita para mostrar o Tamanho da partição +
fdisk [-v]                          +- Versão do programa +

Onde: +
-b  : Faz com que o fdisk mostre na tela a coluna BEGIN +quando utilizar a opção <p> durante o +
       particionamento do disco ou com +a opção -l  quando se for listar as partições +na linha de +
       comando. +
      OBS: Esta opção +é geralmente desnecessária, porque seu valor equivale ao +valor da coluna +
                +START. +
-u  : Muda a unidade de medida padrão para Setores. +Se esta opção for usada  na linha de +
      comando para se fazer o particionamento +de disco, após pressionar <p>, o programa mostrará +
      na tela o inicio e o fim da partição +em Setores ao invés de utilizar cilindros para a listagem. +
      Se for utilizada em conjunto com a opção +-l, a unidade de medida do Inicio e Fim da partição +
      será listada Setores ao invés +de cilindros. +
-l  : Lista as partições existentes no disco, +sem entrar no programa fdisk, ou alterar qualquer +
      partição. Esta opção +é equivalente a entrar no programa fdisk e pressionar <p>, mas +ela +
      somente lista as partições +sem entrar no programa. +
-s  : Mostra o tamanho de uma partição de +disco. A única diferença desta para as outras opções, +é +
      que se deve especificar a unidade mais +a partição que deseja ver o tamanho, por exemplo, +
      digitando-se: +
      fdisk -s /dev/hda1 +
      voce visualizará o tamanho total +da partição de disco hda1. +
-v  : Mostra a versão do programa fdisk que esta +utilizando. +

+ +
  +
+

2.2-) Comandos do fdisk.

+ +

     O fdisk do Linux manipula as partições +de seu disco através de comandos digitados no teclado. Cada letra +digitada corresponde a um comando diferente no fdisk. Estes comandos serão +utilizados após iniciar o programa. +
     Aqui vai a lista de comandos disponíveis +no fdisk, recomendo que anote em um papel, ou imprima esta parte do texto( +ou todo o documento) para que possa consultar estas opções +durante o particionamento do seu disco rígido. +

a  - Seleciona entre partição inicializável +e não inicializável. +
b  - Edita um volume de disco BSD(não usada em computadores +com DOS) +
d  - Apaga uma tabela de partição (Delete) +
l   - Lista os tipos de partições disponíveis +(List) +
m - Ajuda +
n  - Cria uma nova tabela de partição (New) +
p  - Mostra a tabela de partição atual (Print) +
q  - sai do fdisk sem gravar as alterações +no disco (quit) +
t   - Muda o tipo da partição (Type) +
u  - Altera as unidades de medidas que são mostradas +na tela +
v  - Verifica a tabela de partição (verify) +
w - grava as alterações feitas para o disco e +sai do fdisk (write) +
x  - Comandos especiais do programa(somente para usuários +experientes) +

+ +
  +
+

3-) Manipulando partições +no disco rígido

+ +

    Agora vamos começar realmente a trabalhar +com o fdisk, os textos que foram colocados acima, foi para que voce entendesse +o que é o particionamento de um disco rígido e para que soubesse +a diferença entre partição e um disco rígido,(já +vi muitas pessoas falarem de partição como se fosse disco +rígido...) +
     Abaixo uma explicação passo-a-passo +de como particionar um disco usando +
o fdisk e seus comandos. +

ATENÇÃO: O disco rígido usado no particionamento +é um exemplo. Ele não deve ser usado por +
                     +voce para fazer o particionamento de seu disco, uma vez que a capacidade +e outros +
                     +parâmetros do disco rígido variam de um para o outro. Este +exemplo serve apenas +
                     +para que voce entenda como o fdisk funciona, o que faz cada um de seus +comandos +
                     +e a  fazer o cálculo do tamanho das partições. +

   A tradução das mensagens que aparecem em +Ingles nos exemplos que vou colocar logo abaixo, e a ajuda do programa, +não foram feitas porque aparecem exatamente como estão quando +fizer o particionamento de seu disco, e não conheço nenhuma +versão do fdisk(Linux) em português (caso alguém conheça +uma versão deste programa em português, favor entrar em contato +comigo para que eu possa atualizar este documento, meu endereço +de E-mail esta no final do documento). +
    Somente vou explicar o que significa cada mensagem +que aparece no fdisk +
através de uma comparação. +

No exemplo eu vou usar um disco de 1.08GB. Este disco possui +630 +cilindros, 16 cabeças, e 21 setores por trilha( emmodo +LBA). +

+ +
  +
+

3.1-) Listando partições +existentes no disco

+ +

    Primeiro digite fdisk /dev/hda (supondo que +este seja o disco principal), se a unidade de disco não for digitada, +o fdisk usará /dev/hda como padrão. Após voce digitar +este comando, o fdisk procura por partições existentes, seus +tamanhos e outras características(geometria do disco) que serão +utilizadas para se fazer o cálculo de partições. +
    Quando entrar no programa, digite a letra <p> +para que o programa mostre as tabelas de partição existentes +no disco rígido. +

A tela que aparece é a seguinte: +

---------------------------------------------------------------------------------------------------- +
Command (m for help): p +
Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +
Units = cylinders of 630*512 bytes +

 Device      Boot    Begin    +Start    End   Blocks   Id   +System +
 /dev/hda1    *        +1        1      +117   204800    6   DOS 16-bits >=32M +

Command (m for help): +
----------------------------------------------------------------------------------------------------- +
  +

Abaixo uma tradução desta tela: +
----------------------------------------------------------------------------------------------------- +
Commando (m para ajuda): <p> +
Disco /dev/hda: 16 cabeças, 21 setores, 630 cilindros +
Unidades = cilindros de 630*512 bytes +

Dispositivo  Partida  Começa  Inicio   +Fim  Blocos  Identif.  Sistema +
/dev/hda1      *        +1       1      117  +204800     6      DOS 16-bits +>=32M +

Comando (m para ajuda): +
---------------------------------------------------------------------------------------------------- +

Onde: +
Device : É a identificação da partição +de disco. +
Boot     : Se estiver com "*", se a partição +pode ser usada para BOOT. +
Begin    : Cilindro inicial da partição +de disco +
Start     : Cilindro inicial da partição +de disco +
End       : Cilindro Final da +partição do disco +
Blocks   : Quantidade de blocos ocupados pela partição +de disco. No Linux, um +
                +Bloco equivale a 1024 bytes(1KB) +
ID         : Tipo da +partição (conforme a lista de partições existentes +quando é +
              +pressionada a letra <L>. +
System : Descrição do sistema de arquivos que +é usado na partição de disco. +

    Como vemos acima, o disco rígido possui uma +partição do tipo DOS- FAT16 ocupando 200MB +de espaço em disco (200000 Blocos multiplicados por 1024). +

+ +
  +
+

3.2-) Criando uma partição +de Disco

+ +

    Para criar uma partição de disco, pressionamos +a letra <n>. Neste exemplo vamos criar uma partição do +tipo Linux EXT2(Nativa) com o tamanho de 820MB, esta partição +é a que conterá todo o sistema de arquivos Linux e seus programas, +veja o exemplo: +

----------------------------------------------------------------------------------------------------- +
Command ( m for help): <n> +
    e  extended +
    p  primary partition (1-4) +
<p> +
Partition number (1-4): <2> +
First cylinder(118-630): <118> +
Last cylinder or +size or +sizeK or +sizeM (118-630): <+820M> +
----------------------------------------------------------------------------------------------------- +
    O fdisk perguntará se deseja criar uma partição +extendida ou primária. Crie uma partição primária +para o sistema de arquivos do Linux, ou uma partição extendida +caso voce ja tenha 3 partições primárias criadas em +seu disco, conforme foi visto acima. +
    Como pode ter notado no exemplo acima, como já +existia a partição 1, digitamos o número 2 para que +fosse criada uma segunda partição, se a partição +número 2 já existisse, seria digitado o número 3 para +criar uma terceira partição, assim por diante. +
    Após escolher o tipo de partição +que será criada, voce deverá especificar o cilindro inicial +da partição de disco. No exemplo acima, o valor do cilindro +inicial é de 118. Utilize sempre o valor do cilindro inicial sugerido +pelo fdisk, a não ser que se queira deixar um espaço entre +uma partição antiga e a nova partição para +a criação de uma partição menor ou por outros +motivos. +
     O último passo é especificar +onde terminará a partição de disco. É permitida +a utilização de Cilindros, bytes, Kbytes e Mbytes para marcar +o final da partição de disco (veja detalhes abaixo). +

LEMBRE-SE: Em um mesmo disco rígido podem existir até +4 partições primárias (contando com +
                         +a partição Extendida). +

Onde: +
   Partition number : Número da partição +que vai ser criada, como já temos  uma partição +no +
                             +disco, digitamos o número 2 para dizer ao fdisk que queremos criar +uma +
                             +segunda partição primária. Neste exemplo, voce acabou +de criar a +
                             +partição /dev/hda2. +
    First cylinder  : Primeiro cilindro +disponível após o último cilindro usado pela partição +1. Neste +
                             +caso usamos o cilindro 118 até o cilindro final(Last Cylinder). +O valor deve ser +
                             +digitado em cilindros. +
    Last cylinder or +size or +sizeK or +sizeM +: Aqui voce pode especificar o final da partição de +
                             +disco. +
                             +Os seguintes valores podem ser usados para marcar o  final da partição +de +
                             +disco: +

                            +597                +- É o valor equivalente a partição de 820MB  +(em cilindros) +
                            ++820000000  - É o valor equivalente a partição +de  820MB (em bytes) +
                            ++820000K     - É o valor equivalente a partição +de 820MB (em Kbytes) +
                            ++820M           - É +o valor equivalente a partição de 820MB (em Mbytes) +

    Recomendo que especifique o valor em MB ou +KB +por não exigir o cálculo do espaço do disco usado +em cada cilindro, e por ser um dos mais utilizados e mais práticos. +Especificando o valor em bytes, Kbytes ou Mbytes, o fdisk +se encarregará de converter o tamanho digitado para um valor de +cilindro final. +
    Se digitar um número acima do espaço +disponível no disco(ou cilindro diponível), será mostrada +uma mensagem de erro dizendo que a partição não pode +ser criada. +

OBS: Caso seja criada uma partição DOS FAT16, deverá +ser utilizado o comando +
     dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 +
     para que a partição criada seja +compatível com o formato utilizado pelo +
     DOS. Para maiores detalhes veja Observações +sobre o formato DOS 6.XX +
  +

    Para verificar as partições existentes +no disco tecle <p> +
----------------------------------------------------------------------------------------------------- +
Command (m for help): p +
Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +
Units = cylinders of 630*512 bytes +

 Device    Boot  Begin  Start  End   +Blocks    Id     System +
/dev/hda1   *        1      +1    117   204800     6       +DOS 16-bits >=32M +
/dev/hda2         118    +118   597   839680    83     +Linux Native +

Command (m for help): +
----------------------------------------------------------------------------------------------------- +

+ +
  +
  +
+

3.3-) Mudando o tipo de uma partição

+ +

    O tipo da partição é a identificação +de qual sistema de arquvios que ela pertence e na qual possuem características +próprias e diferentes de outros sistemas de arquivos. +
    Tecle <t> para trocar o tipo de partição +usado no disco. +
Pressione a tecla <l> se desejar ver os tipos de partições +compatíveis com o programa fdisk. +
     Veja o exemplo de como trocar o tipo da partição +de Linux Native (tipo 83) para Linux Swap (tipo 82). +
----------------------------------------------------------------------------------------------------- +
  Command (m for help): <t> +
  Partition number (1-4): <3> +
  Hex code (type L to list codes): <82> +
----------------------------------------------------------------------------------------------------- +
    Agora a partição em /dev/hda3 é +do tipo Linux SWAP(tipo 82). +
  +

Pressione a tecla <p> para verificar a partição /dev/hda3: +
----------------------------------------------------------------------------------------------------- +
Command (m for help): p +
Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +
Units = cylinders of 630*512 bytes +

 Device    Boot  Begin  Start  End  +Blocks    Id     System +
/dev/hda1   *      1      +1    117  204800     6    +DOS 16-bits >=32M +
/dev/hda2         118    +118   597  839680    83    +Linux Native +
/dev/hda3         598    +598   630   61440    83    +Linux SWAP +

Command (m for help): +
----------------------------------------------------------------------------------------------------- +

+ +
  +
+

3.4-) Excluindo uma partição +de Disco

+ +

    Para excluir uma partição, pressione +a tecla <d>, será mostrada a seguinte tela: +
---------------------------------------------------------------------------------------------------- +
Command (m for help):<d> +
Partition number(1-4): 3 +

Command(m for help): +
---------------------------------------------------------------------------------------------------- +
    Com o comando acima, a partição número +3 (SWAP) foi excluida,. O espaço ocupado pela partição +3 é novamente liberado para que voce possa utilizar para criar outra +(ou outras) partições de disco. +

ATENÇÃO: TENHA MUITO CUIDADE COM O DA OPÇÃO +<D>(Delete) DO FDISK. +
                     +Caso se tenha apagado acidentalmente alguma partição que +contém dados, pressione +
                      +a tecla <q> para sair do fdisk sem gravar o que fez. Neste caso, será +necessário +
                      +refazer todo o particionamento do disco.  Não pressione a tecla +<w> se voce excluiu +
                      +alguma partição que utiliza, porque todo o que foi feito +no fdisk será gravado, +
                      +inclusive a partição excluida acidentalmente, sem a possibilidade +de recupera-la. +

para verificar se a partição foi excluida pressionamos +<p>: +
----------------------------------------------------------------------------------------------------- +
Command (m for help): p +
Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +
Units = cylinders of 630*512 bytes +

 Device    Boot Begin  Start  End  +Blocks    Id     System +
/dev/hda1   *     1      +1    117  204800     6     +DOS 16-bits >=32M +
/dev/hda2        118    +118   597  839680    83    +Linux Native +
Command (m for help): +
---------------------------------------------------------------------------------------------------- +

+ +
  +
+

3.5-) Gravando partições +alteradas para o disco

+ +

     Para gravar as alterações feitas +na(s) partições para o disco após fazer o particionamento, +pressione a tecla <w>, esta opção faz a saida do fdisk +gravando todas as alterações que fez durante o uso do programa +fdisk(partições criadas, alteradas, excluidas). +
    Enquando voce trabalha no fdisk criando partições, +modificando tamanhos, excluindo partições, nada do que faz +é gravado para o disco automaticamente (por motivos de segurança +contra perda de alguma partição já existente). +

+ +
  +
+

3.6-) Abandonando o particionamento +de disco sem gravar as alterações

+ +

    Para sair do fdisk sem gravar as alterações +para o disco pressione <q>. Esta opção de sair do fdisk +sem gravar as alterações(abandona o programa), é bastante +útil caso tenha apagado acidentalmente uma partição +que contenha arquivos e programas importantes armazenados nela. +

+ +
  +
+

3.7-) Alternando entre partição +inicializável e não inicializável

+ +

     Partição inicializável +é aquela em que o sistema pode dar a partida(boot) no computador. +Pressione a tecla <a> para alterar o tipo da partição +entre inicializável e não inicalizável. +
OBS: O Linux pode iniciar mesmo que a partição +que esta instalado esteja  marcada como não +
          inicializável, +utilizando um boot manager(gerenciador de inicialização) +como o LILO(Linux +
          Loader) ou o +LoadLin no DOS. +

+ +
  +
+

3.8-) Alterando a unidade de medida +do tamanho ocupado pela partição

+ +

    Para alterar de uma unidade de medida para outra, +pressione a tecla <u>. A unidade de medida da partição, +é o valor com que será mostrado o tamanho que a partição +ocupa no disco toda a vez que se pressiona a tecla <p>, para mostrar +as partições na tela, durante o particionamento de disco +ou quando se utilizar a opção -l na linha de comando, para +listar as partições de disco. +

As unidades de medida disponíveis são: +
Cilindros : Este é o padrão do sistema, corresponde +ao local onde começa e +
                 +aonde termina a partição, em cilindros. +
Setores   : corresponde ao local onde começa +e aonde termina a partição, em +
                 +Setores. +

+ +
  +
  +
+

4-) Outros tipos de partições +disponíveis no fdisk(para referência técnica)

+ +

    Abaixo, segue a listagem dos tipos de partições +compatíveis com esta versão do fdisk, que pode servir de +guia durante o processo de particionamento, e para que conheça a +compatibilidade deste programa com os diversos tipos de partições +que suporte. +

OBS1: Recomendo que voce use o programa de particionamento que +acompanha seu sistema +
            +operacional para a criação de seu sistema de arquivos, por +exemplo: +
            +- Para criar uma partição DOS, utilize o Fdisk que acompanha +o  DOS. +
            +- Para criar uma partição Linux, utilize o Fdisk que acompanha +o Linux. +
  +

Tipo     Descrição +

0         Vazio +
1         DOS FAT 12 +
2         Xenix root +
3         Xenix /usr +
4         DOS 16-bits<32MB +
5         Extendida DOS +
6         DOS 16-bits >=32MB +
7         OS/2 HPFS +
8         AIX +
9         AIX inicializável +
a         OS/2 Boot Manager +
40       Venix 80286 +
51       Novell +
52       Microport +
63       GNU hurd +
64       Novell Netware 286 +
65       Novell Netware 386 +
75       PC/IX +
80       OLD Minix +
81       Linux Minix +
82       Linux SWAP +
83       Linux Native +
85       Linux Extendida +
93       Amoeba +
94       Amoeba BBT +
a5       BSD/386 +
a6       Open BSD +
a7       NextStep +
b7       BSDI File System +
b8       BSDI Swap +
c7       Syrinx +
db       CP/M +
e1       DOS access +
e3       DOS R/O +
f2       Dos Secundária +
ff       BBT +

+ +
  +
+

5-) Direitos Autorais

+ +

       Este documento foi desenvolvido +com base em minha experiência e conhecimento em discos e partições, +mediante pesquisa em alguns documentos como os How-TO do Linux e verificando +as principais dúvidas de usuários durante a utilização +de particionadores de disco, tendo como objetivo levar o conhecimento sobre +discos, partições e utilização deste programa, +atendendo tanto usuários iniciantes como avançados e como +contribuição para a comunidade Linux em geral. +
  +
  +
+
+

+

Gleydson M. da Silva (gleydson_s@yahoo.com e gleydson@linuxbr.com.br)

+ +

    Qualquer dúvida, sugestão ou reclamação +podem ser mandadas para um dos E-Mail's Acima. Conto com sua contribuição +para a melhoria deste Manual. +

+

    Autorizo a reprodução Total ou parcial +deste texto para que seja utilizado para fins educativos, autoaprendizado, +colocação em Home pages e qualquer outra forma de distribuição +não comercial do documento desde que sejam mantidos os meus créditos +pela pesquisa e elaboração deste documento de acordo com +os termos da GNU (veja abaixo Licenças e Garantias +sobre este documento).

+  + + +
6- ) Licenças e garantias +sobre este documento
+ +

Fdisk-Portugues-HOWTO Copyright (C) 1999 Gleydson M. da Silva +

    Este é um documento de livre distribuição, +que pode ser copiado e distribuído sob os termos da Licença +Pública Geral  GNU, conforme publicada pela Free Software Foundation, +versão 2 da licença ou (a critério do autor) qualquer +versão posterior. +
   Este documento é distribuído com a itenção +de ser útil ao seu utilizador, no entanto NÃO TEM NENHUMA +GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS OU +DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença +Pública Geral  GNU para maiores detalhes. +

gleydson_s@yahoo.com +
gleydson@linuxbr.com.br +

+ +
  +
+

7- ) Marcas Registradas

+ +

Os programas e referências mencionados neste manual são +de propriedade dos seus respectivos donos: +

MS-DOS, Windows 3.1x, Windows 9x, Windows NT são de propriedade +da Microsoft. +
OS/2 e OS/2 Warp são de propriedade da IBM +

+ +
8- ) Agradecimentos
+ +

Agradeço a todas as pessoas que me mandam correções, +comentários, críticas, elogios, dúvidas sobre este +documento, pois através destas mensagens, estão contribuindo +para a melhoria deste projeto e me icentivando em sua continuação.  +

+<EOF> + + diff --git a/fdisk/doc/Fdisk-Portuguese.txt b/fdisk/doc/Fdisk-Portuguese.txt new file mode 100644 index 00000000..fbf0dcf8 --- /dev/null +++ b/fdisk/doc/Fdisk-Portuguese.txt @@ -0,0 +1,855 @@ + Fdisk-Portuguese Copyright (C) 1999 Gleydson M. da Silva + + + + + + + + + + Gleydson M. da Silva - gleydson@linuxbr.com.br + Versão 1.3 + + + + + + + + + +[ Índice ] + +1 - Introdução ao Fdisk + 1.1 - O que é uma Partição de Disco + 1.2 - A tabela de partição + 1.3 - Introdução ao Particionamento de discos + 1.4 - Identificações utilizadas neste documento + 1.5 - Identificação de discos e partições no Linux + 1.6 - Tipos de partições de disco + 1.7-) Observações sobre o formato DOS 6.XX(FAT 16) + +2 - Iniciando o programa Fdisk + 2.1 - Opções de Linha de comando + 2.2 - Comandos do Fdisk + +3 - Manipulando partições no disco rígido + 3.1 - Listando partições existentes no disco + 3.2 - Criando partições de disco + 3.3 - Mudando o tipo da partição + 3.4 - Excluindo uma partição de disco + 3.5 - Gravando partições alteradas para o disco + 3.6 - Abandonando o programa sem gravar alterações para o disco + 3.7 - Alternando entre partição inicializável/não inicializável + 3.8 - Escolhendo a unidade para mostrar o tamanho ocupado pela partição + +4 - Tipos de partições reconhecídas pelo Fdisk + +5 - Direitos Autorais + +6 - Licenças e Garantias sobre este documento + +7 - Marcas Registradas + +8 - Agradecimentos + + + + + + + + + + + + + +1-) Introdução ao Fdisk + + Fdisk é um programa utilizado para fazer o particionamento de discos rígidos +IDE e SCSI. + A versão do programa Fdisk descrita neste manual é a 2.8 +ATENÇÃO: ESTE MANUAL TEM COMO OBJETIVO A EXPLICAÇÃO DE FUNCIONAMENTO E + UTILIZAÇÃO DO FDISK DO LINUX (NÃO O FDISK DO DOS), MESMO QUE + SEJA UM USUÁRIO DO DOS, EU RECOMENDO QUE LEIA ESTE MANUAL + COMO UMA REFERÊNCIA TÉCNICA E PARA SEU APRENDIZADO. + + Este documento é distribuído com a itenção de ser útil ao seu utilizador, +no entanto NÃO TEM NENHUMA GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS +OU DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença Pública +Geral  GNU para maiores detalhes. + + + +1.1-) Partição de Disco + + Uma partição de disco é o local onde o sistema operacional armazena seu +sistema de arquivos(arquivos, diretórios, FAT, boot sector, etc). + + + +1.2-) Tabela de partição + +A Tabela de partição é o local do disco rígido onde se localizam os dados sobre +todas as partições existentes no disco como o sistema de arquivos utilizado, se +ela é inicializável, a cabeça inicial/final, setor inicial/final, cilindro +inicial/final, número de setores ocupados por ela no disco. + + + +1.3-) Introdução ao particionamento de discos + +Particionar o disco rígido é dividir ele em partes para armazenamento +de arquivos e programas. As partições criadas no disco podem ter o tamanho +que desejar (desde que esteja dentro da capacidade máxima do disco rígido). + +Uma partição não interfere em outras partições do mesmo disco(é como +se tivessemos vários discos rígidos dentro de um). + +Em um disco rígido, pode ser criada uma partição única, que neste caso +todo o disco rígido é usado para armazenar os arquivos(que é o caso mais +comum caso voce tenha o DOS), ou várias partições, que podem ser usadas +pelo mesmo SO(Sistema Operacional) ou outros sistemas operacionais diferentes +(um exemplo de várias partições, é se voce for usar o DOS e o Linux no mesmo +disco, os dois sistemas vão estar no mesmo disco mas um não interfere no +outro). + +Este manual tem a itenção de explicar o particionamento de discos utilizando +o programa fdisk (fdisk do Linux não do DOS!). + + + +1.4-) Algumas identificações utilizadas neste manual para facilitar a + compreensão do texto + +Esta parte descreve algumas características de organização deste manual +e algumas identificações que adotei para facilitar o seu entendimento, e as +explicações que serão dadas. + +Explicação de nomes e comandos, sera seguida da palavra "onde" e abaixo +dela as explicações sobre os comandos, exemplo: + +onde: +nome a ser explicado1 : Descrição +nome a ser explicado2 : Descrição +nome a ser explicado3 : Descrição + +ou + +onde: +nome a ser explicado1 - Descrição +nome a ser explicado2 - Descrição +nome a ser explicado3 - Descrição + + +Quando for feita alguma referência com tecla do teclado, por exemplo, +pressione p para listar as partições, a letra sera colocada entre <> para +facilitar a interpretação: + +pressione

para listar as partições +após isto pressione para confirmar +pressione para listar os tipos de partições disponíveis + + +As linhas pontilhadas que aparecem na tela, veja abaixo, +---------------------------------------------------------------------------- +---------------------------------------------------------------------------- +servem para identificar que o que esta entre as linhas é um exemplo de como +será a resposta do comando para a tela de seu computador. + + + +1.5-) Identificação de discos e partições no Linux + +Antes de descrever como se utiliza o programa fdisk, é importante fazer +algumas explicações sobre a identificação das partições e unidades de disco +no sistema Linux( e outros *nix). Se voce for um usuário que já conhece +a interpretação de discos e partições neste sistema, voce não precisará ler +esta parte. + +No sistema operacional Linux, os dispositivos existentes no computador +(como impressoras, unidades de disquetes, discos rígidos, monitor, placa de +som, etc...) são identificados por um nome referente a este dispositivo e +colocado no diretório /dev (que é utilizado para identificar dispositivos ou +periféricos existentes no computador). + +A identificação dos discos rígidos segue a seguinte forma: + + /dev/hda1 + | | || + | | ||_Número que identifica a partição do disco rígido(1=Primeira, 2=segunda) + | | | + | | |_Letra que identifica o disco rígido(a=primeiro disco, b=segundo disco, etc..) + | | + | |_Sigla HD - Significa que é um disco rígido IDE(Se tiver um SD significa SCSI) + | + |_ Identificação do diretório onde os dispositivos do sistema são armazenados + +OBS: As unidades de disco rígido SCSI, são identificadas com as letras SD + seguida pela letra da unidade e número da partição e os discos IDE são + identificados por HD seguida pela letra da unidade de disco e o número + da partição do disco(como visto acima). + +Abaixo, algumas identificações de disco do sistema Linux: + +/dev/hda1 - Disco rígido IDE primário principal - Primeira partição +/dev/hda2 - Disco rígido IDE primário principal - Segunda partição +/dev/hda3 - Disco rígido IDE primário principal - Terceira partição +/dev/hdb1 - Disco rígido IDE primário escravo - Primeira partição +/dev/hdb2 - Disco rígido IDE primário escravo - Segunda partição +/dev/hdb3 - Disco rígido IDE primário escravo - Terceira partição +/dev/hdc1 - Disco rígido IDE secundário principal - Primeira partição +/dev/hdc2 - Disco rígido IDE secundário principal - Segunda partição +/dev/hdc3 - Disco rígido IDE secundário principal - Terceira partição +/dev/hdd1 - Disco rígido IDE secundário escravo - Primeira partição +/dev/hdd2 - Disco rígido IDE secundário escravo - Segunda partição +/dev/hdd3 - Disco rígido IDE secundário escravo - Terceira partição +/dev/sda1 - Primeiro disco rígido SCSI - Primeira partição +/dev/sda2 - Primeiro disco rígido SCSI - Segunda partição +/dev/sda3 - Primeiro disco rígido SCSI - Terceira partição +/dev/sdb1 - Segundo disco rígido SCSI - Primeira partição +/dev/sdb2 - Segundo disco rígido SCSI - Segunda partição +/dev/sdb3 - Segundo disco rígido SCSI - Terceira partição + +No exemplo acima foram usadas 3 partições por disco, mas podem existir +mais partições no mesmo disco, um exemplo é se o disco rígido possuir +partições Lógicas, que são identificadas no sistemas a partir de /dev/hdx5 +em diante. + +Abaixo um exemplo de como o Linux identifica as partições em cada disco +existente em seu computador: + +Vamos supor que eu tenha 2 discos rígidos: +o 1ºdisco de 2GB e o 2ºdisco de 1GB(Giga Byte ou 1.000 Megas!) + +No primeiro disco(de 2GB), a primeira partição é de 800MB do tipo +FAT16(DOS), a segunda partição é de 1.2GB do tipo EXT2(Linux)(1.2GB+800MB=2GB +que é a capacidade total do disco). Então as partições seriam identificadas +da seguinte forma no Linux: + +/dev/hda - Disco rígido Primário Principal +/dev/hda1 - Primeira partição do primeiro disco rígido (de 800MB do tipo DOS) +/dev/hda2 - Segunda partição do primeiro disco rígido( de 1.2GB do tipo Linux) + +Neste caso estariam disponíveis 800MB para serem usados com o DOS e +1.2GB para o Linux. +Por exemplo, se voce particionar um disco rígido em duas partes e usar +as duas partições no DOS, ele reconhecerá as partições como sendo C: e D:. + +Lembre-se: Quando um disco é particionado, uma partição não interfere + nas outras, repare que quando voce particiona(divide) um disco, + é como se tivesse dois discos rígidos(o único cuidado que + voce deve tomar é com as cópias de segurança, porque se der + um problema de parte eletrônica no disco rígido, por exemplo, + a sua placa controladora queimar ou o cabeçote dele ir pro + espaço, voce perderá as suas 2 partições que estão armazenadas + nele. + + +Voltando ao exemplo das classificações das partições do disco, vamos +para o segundo disco: + +No segundo disco(1GB), eu tenho uma partição de 950MB do tipo FAT16(DOS), +que costumo usar para armazenar arquivos temporários e cópias de segurança +de meu sistema, etc..., e outra de 50MB SWAP(Partição de memória virtual +como descrevi acima)(950MB+50MB=1GB). Então as partições deste disco seriam +identificadas da seguinte forma no Linux: + +/dev/hdb - Disco rígido principal escravo +/dev/hdb1 - Primeira partição do disco acima ( de 950MB do tipo DOS) +/dev/hdb2 - Segunda partição do disco acima ( de 50MB do tipo SWAP) + +No disco acima, 950MB estão disponíveis para serem usados pelo DOS e 50 MB pela +memória virtual (SWAP) do Linux. + +Note que se voce utiliza o MS-DOS, não será possível ver as partições +do Linux e SWAP, porque são imcompatíveis com o formato aceito pelo DOS (ele +identificaria a primeira partição do primeiro disco(800MB) como a unidade C: +e a primeira partição do segundo disco(950MB) como unidade D), mas o +contrário não acontece; O Linux tem total compatibilidade com a partição +DOS FAT12, FAT16, FAT32, OS/2 HPFS, e muitas outras. + + + +1.6-) Tipos de partições de discos + +As partições de disco são divididas em tres tipos: Primária, Extendida +e Lógica. + +Pode se ter no máximo quatro partições primárias e extendidas no mesmo +disco. A partição Primária permite o armazenamento de arquivos e diretórios. +Todos os computadores que possuem somente a unidade C(supondo que voce use o +DOS), usam este tipo de partição para armazenamento de arquivos e inicialização +do sistema operacional. + +Se for preciso criar mais que 4 partições no mesmo disco, será necessário +criar uma partição Extendida. A partição Extendida não pode ser utilizada +para armazenar arquivos. Ela é usada para a criação de outras partições, +dentro dela, que são chamadas de partições Lógicas. + +Uma partição extendida podem conter várias partições Lógicas. As partições +Lógicas podem armazenar arquivos e diretórios(como as partições primárias). + +Um mesmo disco rígido pode armazenar mais de 64 partições independentes +uma das outras. + +OBS: Os arquivos e diretórios podem ser armazenados somente em partições de + disco primárias ou lógicas, a partição extendida não é usada para armazanamento + de arquivos e diretórios. + +Se possuir duas partições em seu computador (C: e D: no DOS), e não +estiver usando a partição D:, a instalação pode ser feita nesta partição +desde que ela tenha o espaço necessário para o sistema operacional Linux, +os programas que desejar instalar, mais a partição SWAP. + + + +1.7-) Observações sobre o formato DOS 6.XX(FAT 16) + +No formato DOS 6.XX(FAT16), o primeiro setor da área de dados da partição +é utilizado frequentemente pelo DOS para armazenamento de dados sobre a +partição de disco, e estes dados são usados pelo sistema para se ter maior +confiabilidade do que os dados armazenados na tabela de partição. O sistema +de arquivos DOS, faz o FDISK(do DOS) limpar os primeiros 512 bytes da área +de dados da partição sempre que uma mudança de tamanho acontecer. + +O formatador do DOS(format) verifica este primeiro setor toda vez que +a upção /U (que é utilizada para não salvar dados para se fazer a desformatação +do disco) é utilizada. + +Isto é considerado uma FALHA no Format(do DOS) e no Fdisk(do DOS). +A opção abaixo deve ser utilizada caso voce crie uma partição do DOS FAT16 +com o Fdisk, que faz com que os primeiros 512 bytes daquela partição +sejam "limpos", para manter a compatibilidade com o DOS. Utilize esta opção +dentro do Linux, após criar a partição com o Fdisk e reiniciar o seu +computador. Foi notado que esta opção só funciona corretamente somente quando +o Sistema Linux estiver instalado em seu computador. Não me responsabilizo +caso utiliza-la a partir de um disquete de recuperação. + +dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 + +onde: +hdx1 - É a identificação da unidade de disco e a partição que foi criada + pelo Fdisk utilizando o sistema de arquivos DOS que terá seu + primeiro setor "limpo". + + +OBS1: Cuidado ao utilizar esta opção, um pequeno descuido pode resultar na + perda de dados do seu disco rígido ou outras partição. + +OBS2: Não utilize este comando com partições que utilizam o sistema de arquivos + FAT32(utilizada nos sistemas operacionais Windows 95 OSR/2 e superiores) + se for utilizada em um disco com este sistema, sua FAT será corrompida, + se isto acontecer, será necessária a re-formatação da partição. + +OBS3: É extremamente recomendado que se utilize o programa de particionamento + que acompanha o seu sistema operacional. Por exemplo, se deseja criar + uma partição DOS 6.XX, utilize o FDisk qua acompanha o DOS. + + + +2-) Iniciando o programa Fdisk + +Para iniciar o programa fdisk(Linux)digite: +fdisk [unidade] + +Onde: +unidade - deve ser a unidade de disco rígido no padrão Linux( /dev/hda, + /dev/hdb, /dev/sda, /dev/sdb, etc... ). Se voce tem apenas 1 + disco rígido IDE, use /dev/hda, para fazer o fdisk trabalhar + com este disco. Se possuir 1 disco SCSI, use /dev/sda + +Se a unidade não for especificada, o programa fdisk usará /dev/hda como +unidade de disco padrão. + +ATENÇÃO : A OPERAÇÃO DE PARTICIONAMENTO DE DISCOS PODE FAZER COM QUE OS DADOS + ARMAZENADOS EM SEU DISCO RÍGIDO SEJAM PERDIDOS, SE FOR USADA + INCORRETAMENTE. É SEMPRE RECOMENDADO RETIRAR UMA CÓPIA DE SEGURANÇA + DOS SEUS ARQUIVOS EXISTENTES NO MICRO ANTES DE SE EXECUTAR UM + PROGRAMA DESTE TIPO, A NÃO SER QUE TENHA CONFIANÇA NO QUE ESTA + FAZENDO E QUE ENTENDEU AS EXPLICAÇÕES SOBRE A IDENTIFICAÇÃO DE + DISCOS RÍGIDOS E SUAS PARTIÇÕES NO SISTEMA. + + + +2.1-) Opções de linha de comando + +Com a utilização de opções de linha de comando, voce pode fazer com que +o programa inicie de uma forma específica, ou personalizada. + +fdisk [-b] [-u] [unidade] - Opções aceitas para o particionamento. +fdisk [-l] [-b] [-u] - Opções aceitas para listar as partições atuais. +fdisk [-s] [unidade] - Opção aceita para mostrar o Tamanho da partição +fdisk [-v] - Versão do programa + +Onde: +-b : Faz com que o fdisk mostre na tela a coluna BEGIN quando utilizar + a opção

durante o particionamento do disco ou com a opção -l + quando se for listar as partições na linha de comando. + OBS: Esta opção é geralmente desnecessária, porque seu valor equivale + ao valor da coluna START. +-u : Muda a unidade de medida padrão para Setores. Se esta opção for usada + na linha de comando para se fazer o particionamento de disco, após + pressionar

, o programa mostrará na tela o inicio e o fim da + partição em Setores ao invés de utilizar cilindros para a listagem. + Se for utilizada em conjunto com a opção -l, a unidade de medida do + Inicio e Fim da partição será listada Setores ao invés de cilindros. +-l : Lista as partições existentes no disco, sem entrar no programa + fdisk, ou alterar qualquer partição. Esta opção é equivalente a + entrar no programa fdisk e pressionar

, mas ela somente lista + as partições sem entrar no programa. +-s : Mostra o tamanho de uma partição de disco. A única diferença desta + para as outras opções, é que se deve especificar a unidade mais a + partição que deseja ver o tamanho, por exemplo, digitando-se: + fdisk -s /dev/hda1 + voce visualizará o tamanho total da partição de disco hda1. +-v : Mostra a versão do programa fdisk que esta utilizando. + + + +2.2-) Comandos do fdisk. + +O fdisk do Linux manipula as partições de seu disco através de comandos +digitados no teclado. Cada letra digitada corresponde a um comando diferente +no fdisk. Estes comandos serão utilizados após iniciar o programa. + +Aqui vai a lista de comandos disponíveis no fdisk, recomendo que anote +em um papel, ou imprima esta parte do texto( ou todo o documento) para que +possa consultar estas opções durante o particionamento do seu disco rígido. + +a - Seleciona entre partição inicializável e não inicializável. +b - Edita um volume de disco BSD(não usada em computadores com DOS) +d - Apaga uma tabela de partição (Delete) +l - Lista os tipos de partições disponíveis (List) +m - Ajuda +n - Cria uma nova tabela de partição (New) +p - Mostra a tabela de partição atual (Print) +q - sai do fdisk sem gravar as alterações no disco (quit) +t - Muda o tipo da partição (Type) +u - Altera as unidades de medidas que são mostradas na tela +v - Verifica a tabela de partição (verify) +w - grava as alterações feitas para o disco e sai do fdisk (write) +x - Comandos especiais do programa(somente para usuários experientes) + + + +3-) Manipulando partições no disco rígido + +Agora vamos começar realmente a trabalhar com o fdisk, os textos que +foram colocados acima, foi para que voce entendesse o que é o particionamento +de um disco rígido e para que soubesse a diferença entre partição e um disco +rígido,(já vi muitas pessoas falarem de partição como se fosse disco rígido...) + +Abaixo uma explicação passo-a-passo de como particionar um disco usando +o fdisk e seus comandos. + +ATENÇÃO: O disco rígido usado no particionamento é um exemplo. Ele não deve + ser usado por voce para fazer o particionamento de seu disco, uma + vez que a capacidade e outros parâmetros do disco rígido variam de + um para o outro. Este exemplo serve apenas para que voce entenda + como o fdisk funciona, o que faz cada um de seus comandos e a + fazer o cálculo do tamanho das partições. + +A tradução das mensagens que aparecem em Ingles nos exemplos que vou colocar +logo abaixo, e a ajuda do programa, não foram feitas porque aparecem exatamente +como estão quando fizer o particionamento de seu disco, e não conheço +nenhuma versão do fdisk(Linux) em português (caso alguém conheça uma versão +deste programa em português, favor entrar em contato comigo para que eu +possa atualizar este documento, meu endereço de E-mail esta no final do +documento). +Somente vou explicar o que significa cada mensagem que aparece no fdisk +através de uma comparação. + +No exemplo eu vou usar um disco de 1.08GB. Este disco possui 630 cilindros, +16 cabeças, e 21 setores por trilha(modo LBA). + + + +3.1-) Listando partições existentes no disco + +Primeiro digite fdisk /dev/hda (supondo que este disco seja o principal), +se a unidade de disco não for digitada, o fdisk usará /dev/hda como padrão. +Após voce digitar este comando, o fdisk procura por partições existentes, +seus tamanhos e outras características(geometria do disco) que serão +utilizadas para se fazer o cálculo de partições. + +Quando entrar no programa, digite a letra

para que o programa mostre +as tabelas de partição existentes no disco rígido. + +A tela que aparece é a seguinte: + +---------------------------------------------------------------------------- +Command (m for help): p +Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +Units = cylinders of 630*512 bytes + + Device Boot Begin Start End Blocks Id System + /dev/hda1 * 1 1 117 204800 6 DOS 16-bits >=32M + +Command (m for help): +----------------------------------------------------------------------------- + + +Abaixo uma tradução desta tela: +---------------------------------------------------------------------------- +Commando (m para ajuda):

+Disco /dev/hda: 16 cabeças, 21 setores, 630 cilindros +Unidades = cilindros de 630*512 bytes + +Dispositivo Partida Começa Inicio Fim Blocos Identif. Sistema +/dev/hda1 * 1 1 117 204800 6 DOS 16-bits >=32M + +Comando (m para ajuda): +---------------------------------------------------------------------------- + +Onde: +Device : É a identificação da partição de disco. +Boot : Se estiver com "*", se a partição pode ser usada para BOOT. +Begin : Cilindro inicial da partição de disco +Start : Cilindro inicial da partição de disco +End : Cilindro Final da partição do disco +Blocks : Quantidade de blocos ocupados pela partição de disco. No Linux, um + Bloco equivale a 1024 bytes(1KB) +ID : Tipo da partição (conforme a lista de partições existentes quando é + pressionada a letra . +System : Descrição do sistema de arquivos que é usado na partição de disco. + +Como vemos acima, o disco rígido possui uma partição do tipo DOS- FAT16 +ocupando 200MB de espaço em disco (200000 Blocos multiplicados por 1024). + + + +3.2-) Criando uma partição de Disco + +Para criar uma partição de disco, pressionamos a letra . Neste +exemplo vamos criar uma partição do tipo Linux EXT2(Nativa) com o tamanho de +820MB, esta partição é a que conterá todo o sistema de arquivos Linux e seus +programas, veja o exemplo: + +---------------------------------------------------------------------------- +Command ( m for help): + e extended + p primary partition (1-4) +

+Partition number (1-4): <2> +First cylinder(118-630): <118> +Last cylinder or +size or +sizeK or +sizeM (118-630): <+820M> +---------------------------------------------------------------------------- +O fdisk perguntará se deseja criar uma partição extendida ou primária. +Crie uma partição primária para o sistema de arquivos do Linux, ou uma +partição extendida caso voce ja tenha 3 partições primárias criadas em seu +disco, conforme foi visto acima. + +Como pode ter notado no exemplo acima, como já existia a partição 1, +digitamos o número 2 para que fosse criada uma segunda partição, se +a partição número 2 já existisse, seria digitado o número 3 para criar +uma terceira partição, assim por diante. + +Após escolher o tipo de partição que será criada, voce deverá especificar +o cilindro inicial da partição de disco. No exemplo acima, o valor do cilindro +inicial é de 118. Utilize sempre o valor do cilindro inicial sugerido pelo +fdisk, a não ser que se queira deixar um espaço entre uma partição antiga e +a nova partição para a criação de uma partição menor ou por outros motivos. + +O último passo é especificar onde terminará a partição de disco. É +permitida a utilização de Cilindros, bytes, Kbytes e Mbytes para marcar o +final da partição de disco (veja detalhes abaixo). + +LEMBRE-SE: Em um mesmo disco rígido podem existir até 4 partições primárias + (contando com a partição Extendida). + +onde: + Partition number : Número da partição que vai ser criada, como já temos + uma partição no disco, digitamos o número 2 para + dizer ao fdisk que queremos criar uma segunda partição + primária. Neste exemplo, voce acabou de criar a + partição /dev/hda2. + First cylinder : Primeiro cilindro disponível após o último cilindro + usado pela partição 1. Neste caso usamos o cilindro + 118 até o cilindro final(Last Cylinder). O valor + deve ser digitado em cilindros. + Last cylinder or +size or +sizeK or +sizeM : Aqui voce pode especificar + o final da partição de disco. + Os seguintes valores podem ser usados para marcar o + final da partição de disco: + + 597 - É o valor equivalente a partição de 820MB + (em cilindros) + +820000000 - É o valor equivalente a partição de + 820MB (em bytes) + +820000K - É o valor equivalente a partição de + 820MB (em Kbytes) + +820M - É o valor equivalente a partição de + 820MB (em Mbytes) + +Recomendo que especifique o valor em MB ou KB por não exigir o +cálculo do espaço do disco usado em cada cilindro, e por ser um dos mais +utilizados e mais práticos. Especificando o valor em bytes, Kbytes ou +Mbytes, o fdisk se encarregará de converter o tamanho digitado para +um valor de cilindro final. + +Se digitar um número acima do espaço disponível no disco(ou cilindro +diponível), será mostrada uma mensagem de erro dizendo que a partição não +pode ser criada. + +OBS: Caso seja criada uma partição DOS FAT16, deverá ser utilizado o comando + dd if=/dev/zero of=/dev/hdx1 bs=512 count=1 + para que a partição criada seja compatível com o formato utilizado pelo + DOS. Para maiores detalhes veja Observações sobre o formato DOS 6.XX + + + Para verificar as partições existentes no disco tecle

+---------------------------------------------------------------------------- +Command (m for help): p +Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +Units = cylinders of 630*512 bytes + + Device Boot Begin Start End Blocks Id System +/dev/hda1 * 1 1 117 204800 6 DOS 16-bits >=32M +/dev/hda2 118 118 597 839680 83 Linux Native + +Command (m for help): +---------------------------------------------------------------------------- + + + + +3.3-) Mudando o tipo de uma partição + +O tipo da partição é a identificação de qual sistema de arquvios que ela +pertence e na qual possuem características próprias e diferentes de outros +sistemas de arquivos. + +Tecle para trocar o tipo de partição usado no disco. +Pressione a tecla se desejar ver os tipos de partições compatíveis +com o programa fdisk. + +Veja o exemplo de como trocar o tipo da partição de Linux Native (tipo +83) para Linux Swap (tipo 82): + +---------------------------------------------------------------------------- + Command (m for help): + Partition number (1-4): <3> + Hex code (type L to list codes): <82> +---------------------------------------------------------------------------- + Agora a partição em /dev/hda3 é do tipo Linux SWAP(tipo 82). + + +Pressione a tecla

para verificar a partição /dev/hda3: +---------------------------------------------------------------------------- +Command (m for help): p +Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +Units = cylinders of 630*512 bytes + + Device Boot Begin Start End Blocks Id System +/dev/hda1 * 1 1 117 204800 6 DOS 16-bits >=32M +/dev/hda2 118 118 597 839680 83 Linux Native +/dev/hda3 598 598 630 61440 83 Linux SWAP +Command (m for help): +---------------------------------------------------------------------------- + + + +3.4-) Excluindo uma partição de Disco + +Para excluir uma partição, pressione a tecla , será mostrada a seguinte +tela: + +---------------------------------------------------------------------------- +Command (m for help): +Partition number(1-4): 3 + +Command(m for help): +---------------------------------------------------------------------------- + +Com o comando acima, a partição número 3 (SWAP) foi excluida,. O espaço +ocupado pela partição 3 é novamente liberado para que voce possa utilizar +para criar outra (ou outras) partições de disco. + +ATENÇÃO: TENHA MUITO CUIDADE COM O DA OPÇÃO (Delete) DO FDISK. Caso se + tenha apagado acidentalmente alguma partição que contém dados, + pressione a tecla para sair do fdisk sem gravar o que fez. + Neste caso, será necessário refazer todo o particionamento do disco. + Não pressione a tecla se voce excluiu alguma partição que + utiliza, porque todo o que foi feito no fdisk será gravado, inclusive + a partição excluida acidentalmente, sem a possibilidade de + recupera-la. + +para verificar se a partição foi excluida pressionamos

: +---------------------------------------------------------------------------- +Command (m for help): p +Disk /dev/hda: 16 heads, 21 sectors, 630 cylinders +Units = cylinders of 630*512 bytes + + Device Boot Begin Start End Blocks Id System +/dev/hda1 * 1 1 117 204800 6 DOS 16-bits >=32M +/dev/hda2 118 118 597 839680 83 Linux Native +Command (m for help): +---------------------------------------------------------------------------- + + + +3.5-) Gravando partições alteradas para o disco + +Para gravar as alterações feitas na(s) partições para o disco após +fazer o particionamento, pressione a tecla , esta opção faz a saida do +fdisk gravando todas as alterações que fez durante o uso do programa +fdisk(partições criadas, alteradas, excluidas). + +Enquando voce trabalha no fdisk criando partições, modificando tamanhos, +excluindo partições, nada do que faz é gravado para o disco automaticamente +(por motivos de segurança contra perda de alguma partição já existente). + + + +3.6-) Abandonando o particionamento de disco sem gravar as alterações + +Para sair do fdisk sem gravar as alterações para o disco pressione . +Esta opção de sair do fdisk sem gravar as alterações(abandona o programa), +é bastante útil caso tenha apagado acidentalmente uma partição que contenha +arquivos e programas importantes armazenados nela. + + + +3.7-) Alternando entre partição inicializável e não inicializável + +Partição inicializável é aquela em que o sistema pode dar a partida(boot). +Pressione a tecla para alterar o tipo da partição entre inicializável +e não inicalizável. + +OBS: O Linux pode iniciar mesmo que a partição que esta instalado esteja + marcada como não inicializável, utilizando um boot manager(gerenciador + de inicialização) como o LILO(Linux Loader) ou o LoadLin no DOS. + + + +3.8-) Alterando a unidade de medida do tamanho ocupado pela partição + +Para alterar de uma unidade de medida para outra, pressione a tecla . +A unidade de medida da partição, é o tipo de valor que mostrará o tamanho +que a partição ocupa no disco toda a vez que se pressiona a tecla

, para +mostrar as partições na tela, durante o particionamento de disco ou quando +se utilizar a opção -l na linha de comando, para listar as partições de +disco. + +As unidades de medida disponíveis são: +Cilindros : Este é o padrão do sistema, corresponde ao local onde começa e + aonde termina a partição, em cilindros. +Setores : corresponde ao local onde começa e aonde termina a partição, em + setores. + + + + +4-) Outros tipos de partições disponíveis no fdisk(para referência técnica) + +Abaixo, segue a listagem dos tipos de partições compatíveis com esta versão +do fdisk, que pode servir de guia durante o processo de particionamento, e +para que conheça a compatibilidade deste programa com os diversos tipos +de partições que suporte. + +OBS1: Recomendo que voce use o programa de particionamento específico de + seu sistema operacional, por exemplo: + Para criar uma partição DOS, utilize o Fdisk do dos. + Para criar uma partição Linux, utilize o Fdisk dele. + + +Tipo Descrição + +0 Vazio +1 DOS FAT 12 +2 Xenix root +3 Xenix /usr +4 DOS 16-bits<32MB +5 Extendida DOS +6 DOS 16-bits >=32MB +7 OS/2 HPFS +8 AIX +9 AIX inicializável +a OS/2 Boot Manager +40 Venix 80286 +51 Novell +52 Microport +63 GNU hurd +64 Novell Netware 286 +65 Novell Netware 386 +75 PC/IX +80 OLD Minix +81 Linux Minix +82 Linux SWAP +83 Linux Native +85 Linux Extendida +93 Amoeba +94 Amoeba BBT +a5 BSD/386 +a6 Open BSD +a7 NextStep +b7 BSDI File System +b8 BSDI Swap +c7 Syrinx +db CP/M +e1 DOS access +e3 DOS R/O +f2 Dos Secundária +ff BBT + + + +5-) Direitos Autorais + +Este documento foi desenvolvido com base em minha experiência e conhecimento +em discos e partições, mediante pesquisa em alguns documentos como os How-TO's +do Linux, e verificando as principais dúvidas de usuários durante a utilização +de particionadores de disco, tendo como objetivo levar o conhecimento sobre +discos, partições e utilização deste programa, atendendo tanto usuários +iniciantes como avançados e como contribuição para a comunidade Linux em geral. + +Gleydson M. da Silva (gleydson_s@yahoo.com e gleydson@linuxbr.com.br) + +Qualquer dúvida, sugestão ou reclamação podem ser mandadas para um dos E-Mail's +Acima. Conto com sua contribuição para a melhoria deste Manual. + +Autorizo a reprodução Total ou parcial deste texto para que seja utilizado para +fins educativos, autoaprendizado, colocação em Home pages e qualquer outra forma +de distribuição não comercial do documento desde que sejam mantidos os meus +créditos pela pesquisa e elaboração deste documento de acordo com os termos da +GNU (veja baixo Licenças e Garantias sobre este documento). + + +6- ) Licenças e garantias sobre este documento + +Fdisk-Portuguese Copyright (C) 1999 Gleydson M. da Silva +  +Este é um documento de livre distribuição, que pode ser copiado e +distribuído sob os termos da Licença Pública Geral  GNU, conforme publicada +pela Free Software Foundation, versão 2 da licença ou (a critério do autor) +qualquer versão posterior. + +Este documento é distribuído com a itenção de ser útil ao seu utilizador, +no entanto NÃO TEM NENHUMA GARANTIA,  EXPLÍCITAS OU IMPLÍCITAS , COMERCIAIS +OU DE ATENDIMENTO A UMA DETERMINADA FINALIDADE. Consulte a Licença Pública +Geral  GNU para maiores detalhes. + +gleydson_s@yahoo.com +gleydson@linuxbr.com.br + + + +7- ) Marcas Registradas + +Os programas e referências mencionados neste manual são de propriedade dos +seus respectivos donos: + +MS-DOS, Windows 3.1x, Windows 9x, Windows NT são de propriedade da Microsoft. +OS/2 e OS/2 Warp são de propriedade da IBM + + +8- Agradecimentos + +Agradeço a todas as pessoas que me mandam correções, comentários, críticas, +elogios, dúvidas sobre este documento, pois através destas mensagens, estão +contribuindo para a melhoria deste projeto e me icentivando para sua continuação. + + \ No newline at end of file diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8 index 6307b98e..e26baf1c 100644 --- a/fdisk/fdisk.8 +++ b/fdisk/fdisk.8 @@ -5,9 +5,9 @@ .SH NAME fdisk \- Partition table manipulator for Linux .SH SYNOPSIS -.BI "fdisk [\-u] [" device ] +.BI "fdisk [\-u] " device .sp -.BI "fdisk \-l [\-u] [" "device ..." ] +.BI "fdisk \-l [\-u] " "device ..." .sp .BI "fdisk \-s " "partition ..." .sp @@ -189,20 +189,6 @@ of cylinders. The .I size of the partition (in blocks) is printed on the standard output. -This value is normally used as an argument to the -.BR mkfs (8) -program to specify the size of the partition which will be formatted. -(Older versions of fdisk would do this only if the partition id is -greater than 10, in an attempt to refuse DOS partitions; -this test has been deleted.) -Note that -.B "sfdisk -s" -gives different (namely, correct) answers. -Reasons for the difference are that the kernel and -.B fdisk -need not have the same idea about partition numbering -(e.g., in case you have BSD slices), and have different -ideas about the size of an extended partition. .SH BUGS There are several *fdisk programs around. Each has its problems and strengths. @@ -210,6 +196,20 @@ Try them in the order .BR cfdisk , .BR fdisk , .BR sfdisk . +(Indeed, +.B cfdisk +is a beautiful program that has strict requirements on +the partition tables it accepts, and produces high quality partition +tables. Use it if you can. +.B fdisk +is a buggy program that does fuzzy things - usually it happens to +produce reasonable results. Its single advantage is that it has +some support for BSD disk labels and other non-DOS partition tables. +Avoid it if you can. +.B sfdisk +is for hackers only - the user interface is terrible, but it is +more correct than fdisk and more powerful than both fdisk and cfdisk. +Moreover, it can be used noninteractively.) .PP The IRIX/SGI type disklabel is currently not supported by the kernel. Moreover, IRIX/SGI header directories are not fully supported yet. diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 8cdc6df8..8270d344 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -66,6 +66,22 @@ * 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. + * Corrected single-cylinder partition creating a little, now that + * ankry@mif.pg.gda.pl pointed out a bug; there are more bugs -- aeb, 990214. + * + * Sat Mar 20 09:31:05 EST 1999 Arnaldo Carvalho de Melo + * Internationalization + * + * Corrected deleting last logical partition -- aeb, 990430. + * Removed all assumptions on file names -- aeb, 990709 + * [modprobe gave ugly error messages, and the number of devices to probe + * increased all the time: hda, sda, eda, rd/c0d0, ida/c0d0, ... + * Also partition naming was very ugly.] + * + * Corrected a bug where creating an extended hda3, say, then a logical hda5 + * that does not start at the beginning of hda3, then a logical hda6 that does + * start at the beginning of hda3 would wipe out the partition table describing + * hda5. [Patch by Klaus G. Wagner" ] -- aeb, 990711 */ @@ -78,6 +94,8 @@ #include #include #include +#include +#include "nls.h" #include #include @@ -85,6 +103,7 @@ #include /* for HDIO_GETGEO */ #include /* for BLKRRPART, BLKGETSIZE */ +#include "common.h" #include "fdisk.h" #include "fdisksunlabel.h" @@ -92,6 +111,10 @@ #include "fdiskaixlabel.h" #include "../version.h" +#include "../defines.h" +#ifdef HAVE_blkpg_h +#include +#endif #define hex_val(c) ({ \ char _c = (c); \ @@ -100,8 +123,6 @@ }) -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" #define LINE_LENGTH 80 #define offset(b, n) ((struct partition *)((b) + 0x1be + \ (n) * sizeof(struct partition))) @@ -175,7 +196,7 @@ get_nr_sects(struct partition *p) { /* normally O_RDWR, -l option gives O_RDONLY */ static int type_open = O_RDWR; -char *disk_device = DEFAULT_DEVICE, /* hda, unless specified */ +char *disk_device, /* must be specified */ *line_ptr, /* interactive input */ line_buffer[LINE_LENGTH], changed[MAXIMUM_PARTS], /* marks changed buffers */ @@ -195,8 +216,8 @@ uint heads, cylinders, sector_size = DEFAULT_SECTOR_SIZE, sector_offset = 1, - display_factor = 1, /* in units/sector */ - unit_flag = 1, + units_per_sector = 1, + display_in_cyl_units = 1, extended_offset = 0, /* offset of link pointers */ offsets[MAXIMUM_PARTS] = {0, 0, 0, 0}; @@ -210,58 +231,6 @@ struct partition *part_table[MAXIMUM_PARTS] /* partitions */ *ext_pointers[MAXIMUM_PARTS] /* link pointers */ = {NULL, NULL, NULL, NULL}; -struct systypes sys_types[] = { - {0x00, "Empty"}, - {0x01, "DOS 12-bit FAT"}, - {0x02, "XENIX root"}, - {0x03, "XENIX usr"}, - {0x04, "DOS 16-bit <32M"}, - {0x05, "Extended"}, - {0x06, "DOS 16-bit >=32M"}, - {0x07, "OS/2 HPFS"}, /* or QNX? */ - {0x08, "AIX"}, - {0x09, "AIX bootable"}, - {0x0a, "OS/2 Boot Manager"}, - {0x0b, "Win95 FAT32"}, - {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? */ - {0x64, "Novell Netware 286"}, - {0x65, "Novell Netware 386"}, - {0x75, "PC/IX"}, - {0x80, "Old MINIX"}, /* Minix 1.4a and earlier */ - - {LINUX_PARTITION, "Linux/MINIX"}, /* Minix 1.4b and later */ - {LINUX_SWAP, "Linux swap"}, - {LINUX_NATIVE, "Linux native"}, - {LINUX_EXTENDED, "Linux extended"}, - - {0x93, "Amoeba"}, - {0x94, "Amoeba BBT"}, /* (bad block table) */ - {0xa5, "BSD/386"}, - {0xa6, "OpenBSD"}, - {0xa7, "NEXTSTEP"}, - {0xb7, "BSDI fs"}, - {0xb8, "BSDI swap"}, - {0xc7, "Syrinx"}, - {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 } -}; - jmp_buf listingbuf; void fatal(enum failure why) @@ -275,39 +244,53 @@ void fatal(enum failure why) } switch (why) { - case usage: message = -"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" + case usage: message = _( +"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"; +"-b 2048: (for certain MO drives) use 2048-byte sectors\n"); + break; + case usage2: + /* msg in cases where fdisk used to probe */ + message = _( +"Usage: fdisk [-l] [-b SSZ] [-u] device\n" +"E.g.: fdisk /dev/hda (for the first IDE disk)\n" +" or: fdisk /dev/sdc (for the third SCSI disk)\n" +" or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n" +" or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n" +" ...\n"); break; case no_device: - message = "A disk block device is needed.\n"; + 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"; + 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); + sprintf(error, _("Unable to open %s\n"), disk_device); break; case unable_to_read: - sprintf(error, "Unable to read %s\n", disk_device); + sprintf(error, _("Unable to read %s\n"), disk_device); break; case unable_to_seek: - sprintf(error, "Unable to seek on %s\n", disk_device); + sprintf(error, _("Unable to seek on %s\n"),disk_device); break; case unable_to_write: - sprintf(error, "Unable to write %s\n", disk_device); + sprintf(error, _("Unable to write %s\n"), disk_device); + break; + case ioctl_error: + sprintf(error, _("BLKGETSIZE ioctl failed on %s\n"), + disk_device); break; case out_of_memory: - message = "Unable to allocate any more memory\n"; + message = _("Unable to allocate any more memory\n"); break; - default: message = "Fatal error\n"; + default: message = _("Fatal error\n"); } fputc('\n', stderr); @@ -317,104 +300,107 @@ void fatal(enum failure why) void menu(void) { - if (sun_label) - puts("Command action\n" - " a toggle a read only flag\n" /* sun */ - " b edit bsd disklabel\n" - " c toggle the mountable flag\n" /* sun */ - " 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" - " s create a new empty Sun disklabel\n" /* sun */ - " 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" - " 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" - " b edit bsd disklabel\n" - " c toggle the dos compatibility flag\n" - " 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" - " x extra functionality (experts only)" - ); + if (sun_label) { + puts(_("Command action")); + puts(_(" a toggle a read only flag")); /* sun */ + puts(_(" b edit bsd disklabel")); + puts(_(" c toggle the mountable flag")); /* sun */ + puts(_(" d delete a partition")); + puts(_(" l list known partition types")); + puts(_(" m print this menu")); + puts(_(" n add a new partition")); + puts(_(" o create a new empty DOS partition table")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" s create a new empty Sun disklabel")); /* sun */ + puts(_(" t change a partition's system id")); + puts(_(" u change display/entry units")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + puts(_(" x extra functionality (experts only)")); + } + else if(sgi_label) { + puts(_("Command action")); + puts(_(" a select bootable partition")); /* sgi flavour */ + puts(_(" b edit bootfile entry")); /* sgi */ + puts(_(" c select sgi swap partition")); /* sgi flavour */ + puts(_(" d delete a partition")); + puts(_(" l list known partition types")); + puts(_(" m print this menu")); + puts(_(" n add a new partition")); + puts(_(" o create a new empty DOS partition table")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" s create a new empty Sun disklabel")); /* sun */ + puts(_(" t change a partition's system id")); + puts(_(" u change display/entry units")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + } + else if(aix_label) { + puts(_("Command action")); + puts(_(" m print this menu")); + puts(_(" o create a new empty DOS partition table")); + puts(_(" q quit without saving changes")); + puts(_(" s create a new empty Sun disklabel")); /* sun */ + } + else { + puts(_("Command action")); + puts(_(" a toggle a bootable flag")); + puts(_(" b edit bsd disklabel")); + puts(_(" c toggle the dos compatibility flag")); + puts(_(" d delete a partition")); + puts(_(" l list known partition types")); + puts(_(" m print this menu")); + puts(_(" n add a new partition")); + puts(_(" o create a new empty DOS partition table")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" s create a new empty Sun disklabel")); /* sun */ + puts(_(" t change a partition's system id")); + puts(_(" u change display/entry units")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + puts(_(" x extra functionality (experts only)")); + } } void xmenu(void) { - if (sun_label) - puts("Command action\n" - " a change number of alternate cylinders\n" /* sun */ - " c change number of cylinders\n" - " d print the raw data in the partition table\n" - " e change number of extra sectors per cylinder\n" /*sun*/ - " h change number of heads\n" - " i change interleave factor\n" /* sun */ - " o change rotation speed (rpm)\n" /* sun */ - " m print this menu\n" - " p print the partition table\n" - " q quit without saving changes\n" - " r return to main menu\n" - " s change number of sectors\n" - " v verify the partition table\n" - " w write table to disk and exit\n" - " y change number of physical cylinders" /* sun */ - ); - else - puts("Command action\n" - " 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 */ - " 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" - " q quit without saving changes\n" - " r return to main menu\n" - " s change number of sectors\n" - " v verify the partition table\n" - " w write table to disk and exit" - ); + if (sun_label) { + puts(_("Command action")); + puts(_(" a change number of alternate cylinders")); /*sun*/ + puts(_(" c change number of cylinders")); + puts(_(" d print the raw data in the partition table")); + puts(_(" e change number of extra sectors per cylinder"));/*sun*/ + puts(_(" h change number of heads")); + puts(_(" i change interleave factor")); /*sun*/ + puts(_(" o change rotation speed (rpm)")); /*sun*/ + puts(_(" m print this menu")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" r return to main menu")); + puts(_(" s change number of sectors/track")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + puts(_(" y change number of physical cylinders")); /*sun*/ + } + else { + puts(_("Command action")); + puts(_(" b move beginning of data in a partition")); /* !sun */ + puts(_(" c change number of cylinders")); + puts(_(" d print the raw data in the partition table")); + puts(_(" e list extended partitions")); /* !sun */ + puts(_(" g create an IRIX partition table")); /* sgi */ + puts(_(" h change number of heads")); + puts(_(" m print this menu")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" r return to main menu")); + puts(_(" s change number of sectors/track")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + } } int @@ -428,7 +414,7 @@ struct systypes * get_sys_types(void) { return ( sun_label ? sun_sys_types : - sgi_label ? sgi_sys_types : sys_types); + sgi_label ? sgi_sys_types : i386_sys_types); } char *partition_type(unsigned char type) @@ -437,8 +423,8 @@ char *partition_type(unsigned char type) struct systypes *types = get_sys_types(); for (i=0; types[i].name; i++) - if (types[i].index == type) - return types[i].name; + if (types[i].type == type) + return _(types[i].name); return NULL; } @@ -457,7 +443,7 @@ void list_types(struct systypes *sys) do { printf("%c%2x %-15.15s", i ? ' ' : '\n', - sys[next].index, sys[next].name); + sys[next].type, _(sys[next].name)); next = last[i++] + done; if (i > 3 || next >= last[i]) { i = 0; @@ -501,7 +487,7 @@ int test_c(char **m, char *mesg) { int val = 0; if (!*m) - fprintf(stderr, "You must set"); + fprintf(stderr, _("You must set")); else { fprintf(stderr, " %s", *m); val = 1; @@ -515,16 +501,16 @@ int warn_geometry(void) char *m = NULL; int prev = 0; if (!heads) - prev = test_c(&m, "heads"); + prev = test_c(&m, _("heads")); if (!sectors) - prev = test_c(&m, "sectors"); + prev = test_c(&m, _("sectors")); if (!cylinders) - prev = test_c(&m, "cylinders"); + prev = test_c(&m, _("cylinders")); if (!m) return 0; fprintf(stderr, - "%s%s.\nYou can do this from the extra functions menu.\n", - prev ? " and " : " ", m); + _("%s%s.\nYou can do this from the extra functions menu.\n"), + prev ? _(" and ") : " ", m); return 1; } @@ -532,10 +518,10 @@ void update_units(void) { int cyl_units = heads * sectors; - if (unit_flag && cyl_units) - display_factor = cyl_units; + if (display_in_cyl_units && cyl_units) + units_per_sector = cyl_units; else - display_factor = 1; /* in sectors */ + units_per_sector = 1; /* in sectors */ } void warn_cylinders(void) @@ -558,11 +544,14 @@ void read_extended(struct partition *p) ext_pointers[ext_index] = part_table[ext_index]; if (!get_start_sect(p)) - fprintf(stderr, "Bad offset in primary extended partition\n"); + fprintf(stderr, _("Bad offset in primary extended partition\n")); else while (IS_EXTENDED (p->sys_ind)) { if (partitions >= MAXIMUM_PARTS) { + /* This is not a Linux restriction, but + this program uses arrays of size MAXIMUM_PARTS. + Do not try to `improve' this test. */ fprintf(stderr, - "Warning: deleting partitions after %d\n", + _("Warning: deleting partitions after %d\n"), partitions); clear_partition(ext_pointers[partitions - 1]); changed[partitions - 1] = 1; @@ -583,16 +572,16 @@ void read_extended(struct partition *p) for (i = 0; i < 4; i++, p++) { if (IS_EXTENDED (p->sys_ind)) { if (ext_pointers[partitions]) - fprintf(stderr, "Warning: extra link " + fprintf(stderr, _("Warning: extra link " "pointer in partition table " - "%d\n", partitions + 1); + "%d\n"), partitions + 1); else ext_pointers[partitions] = p; } else if (p->sys_ind) { if (part_table[partitions]) fprintf(stderr, - "Warning: ignoring extra data " - "in partition table %d\n", + _("Warning: ignoring extra data " + "in partition table %d\n"), partitions + 1); else part_table[partitions] = p; @@ -617,9 +606,9 @@ void create_doslabel(void) int i; fprintf(stderr, - "Building a new DOS disklabel. Changes will remain in memory only,\n" - "until you decide to write them. After that, of course, the previous\n" - "content won't be recoverable.\n\n"); + _("Building a new DOS disklabel. Changes will remain in memory only,\n" + "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 */ @@ -653,9 +642,20 @@ int get_boot(enum action what) if ((fd = open(disk_device, O_RDONLY)) < 0) fatal(unable_to_open); else - printf("You will not be able to write the partition table.\n"); + printf(_("You will not be able to write the partition table.\n")); } +#if defined(BLKSSZGET) && defined(HAVE_blkpg_h) + /* For a short while BLKSSZGET gave a wrong sector size */ + { int arg; + if (ioctl(fd, BLKSSZGET, &arg) == 0) + sector_size = arg; + if (sector_size != DEFAULT_SECTOR_SIZE) + printf(_("Note: sector size is %d (not %d)\n"), + sector_size, DEFAULT_SECTOR_SIZE); + } +#endif + guess_device_type(fd); if (sector_size != read(fd, buffer, sector_size)) @@ -673,10 +673,11 @@ int get_boot(enum action what) if (dos_compatible_flag) sector_offset = sectors; } else { - if (!ioctl(fd, BLKGETSIZE, §ors)) { + long longsectors; + if (!ioctl(fd, BLKGETSIZE, &longsectors)) { heads = 1; cylinders = 1; - sectors /= sec_fac; + sectors = longsectors / sec_fac; } else { heads = cylinders = sectors = 0; } @@ -698,8 +699,8 @@ got_table: switch(what) { case fdisk: fprintf(stderr, - "Device contains neither a valid DOS partition" - " table, nor Sun or SGI disklabel\n"); + _("Device contains neither a valid DOS partition" + " table, nor Sun or SGI disklabel\n")); #ifdef __sparc__ create_sunlabel(); #else @@ -714,7 +715,7 @@ got_table: break; } - fprintf(stderr, "Internal error\n"); + fprintf(stderr, _("Internal error\n")); exit(1); } @@ -724,15 +725,15 @@ got_table: for (i = 0; i < 4; i++) if(IS_EXTENDED (part_table[i]->sys_ind)) { if (partitions != 4) - fprintf(stderr, "Ignoring extra extended " - "partition %d\n", i + 1); + 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, - "Warning: invalid flag 0x%04x of partition " - "table %d will be corrected by w(rite)\n", + _("Warning: invalid flag 0x%04x of partition " + "table %d will be corrected by w(rite)\n"), part_table_flag(buffers[i]), i + 1); changed[i] = 1; } @@ -744,9 +745,19 @@ got_table: int read_line(void) { + static int got_eof = 0; + line_ptr = line_buffer; - if (!fgets(line_buffer, LINE_LENGTH, stdin)) + if (!fgets(line_buffer, LINE_LENGTH, stdin)) { + if (feof(stdin)) + got_eof++; /* user typed ^D ? */ + if (got_eof >= 3) { + fflush(stdout); + fprintf(stderr, _("\ngot EOF thrice - exiting..\n")); + exit(1); + } return 0; + } while (*line_ptr && !isgraph(*line_ptr)) line_ptr++; return *line_ptr; @@ -779,7 +790,7 @@ read_hex(struct systypes *sys) while (1) { - read_char("Hex code (type L to list codes): "); + read_char(_("Hex code (type L to list codes): ")); if (tolower(*line_ptr) == 'l') list_types(sys); else if (isxdigit (*line_ptr)) @@ -818,7 +829,7 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg) default_ok = 0; if (default_ok) - sprintf(ms, "%s (%d-%d, default %d): ", mesg, low, high, dflt); + sprintf(ms, _("%s (%d-%d, default %d): "), mesg, low, high, dflt); else sprintf(ms, "%s (%d-%d): ", mesg, low, high); @@ -839,26 +850,26 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg) switch (*line_ptr) { case 'c': case 'C': - if (!unit_flag) + if (!display_in_cyl_units) i *= heads * sectors; break; case 'k': case 'K': i *= 2; i /= (sector_size / 512); - i /= display_factor; + i /= units_per_sector; break; case 'm': case 'M': i *= 2048; i /= (sector_size / 512); - i /= display_factor; + i /= units_per_sector; break; case 'g': case 'G': i *= 2048000; i /= (sector_size / 512); - i /= display_factor; + i /= units_per_sector; break; default: break; @@ -872,18 +883,18 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg) } } if (use_default) - printf("Using default value %d\n", i = dflt); + printf(_("Using default value %d\n"), i = dflt); if (i >= low && i <= high) break; else - printf("Value out of range.\n"); + printf(_("Value out of range.\n")); } return i; } int get_partition(int warn, int max) { - int i = read_int(1, 0, max, 0, "Partition number") - 1; + int i = read_int(1, 0, max, 0, _("Partition number")) - 1; if (warn && ( (!sun_label && !sgi_label && !part_table[i]->sys_ind) @@ -891,23 +902,24 @@ int get_partition(int warn, int max) (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id)) || (sgi_label && (!sgi_get_num_sectors(i))) - )) fprintf(stderr, "Warning: partition %d has empty type\n", i+1); + )) fprintf(stderr, _("Warning: partition %d has empty type\n"), i+1); return i; } -char *const str_units(void) +char *const str_units(int n) /* n==1: use singular */ { - return unit_flag ? "cylinder" : "sector"; + if (n == 1) + return display_in_cyl_units ? _("cylinder") : _("sector"); + else + return display_in_cyl_units ? _("cylinders") : _("sectors"); } void change_units(void) { - if ((unit_flag = !unit_flag)) - display_factor = 1; - else display_factor = heads * sectors; + display_in_cyl_units = !display_in_cyl_units; update_units(); - printf("Changing display/entry units to %ss\n", - str_units()); + printf(_("Changing display/entry units to %s\n"), + str_units(PLURAL)); } void toggle_active(int i) @@ -916,7 +928,7 @@ void toggle_active(int i) if (IS_EXTENDED (p->sys_ind) && !p->boot_ind) fprintf(stderr, - "WARNING: Partition %d is an extended partition\n", + _("WARNING: Partition %d is an extended partition\n"), i + 1); if (p->boot_ind) p->boot_ind = 0; @@ -927,14 +939,14 @@ void toggle_active(int i) void toggle_dos(void) { dos_compatible_flag = ~dos_compatible_flag; - printf("DOS Compatibility flag is "); - if (dos_compatible_flag) + if (dos_compatible_flag) { sector_offset = sectors; + printf(_("DOS Compatibility flag is set\n")); + } else { sector_offset = 1; - printf("not "); + printf(_("DOS Compatibility flag is not set\n")); } - printf("set\n"); } void delete_partition(int i) @@ -969,6 +981,7 @@ void delete_partition(int i) else if (!q->sys_ind && i > 4) { free(buffers[--partitions]); clear_partition(ext_pointers[--i]); + changed[i] = 1; } else if (i > 3) { if (i > 4) { @@ -1018,39 +1031,39 @@ void change_sysid(void) origsys = sys = get_sysid(i); if (!sys && !sgi_label) - printf("Partition %d does not exist yet!\n", i + 1); + printf(_("Partition %d does not exist yet!\n"), i + 1); else while (1) { sys = read_hex (get_sys_types()); if (!sys && !sgi_label) { - printf("Type 0 means free space to many systems\n" + 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"); + "a partition using the `d' command.\n")); /* break; */ } if (!sun_label && !sgi_label) { if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) { - printf("You cannot change a partition into" + printf(_("You cannot change a partition into" " an extended one or vice versa\n" - "Delete it first.\n"); + "Delete it first.\n")); break; } } if (sys < 256) { if (sun_label && i == 2 && sys != WHOLE_DISK) - printf("Consider leaving partition 3 " + printf(_("Consider leaving partition 3 " "as Whole disk (5),\n" "as SunOS/Solaris expects it and " - "even Linux likes it.\n\n"); + "even Linux likes it.\n\n")); if (sgi_label && ((i == 10 && sys != ENTIRE_DISK) || (i == 8 && sys != 0))) - printf("Consider leaving partition 9 " + printf(_("Consider leaving partition 9 " "as volume header (0),\nand " "partition 11 as entire volume (6)" - "as IRIX expects it.\n\n"); + "as IRIX expects it.\n\n")); if (sys == origsys) break; @@ -1061,10 +1074,10 @@ void change_sysid(void) 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, + printf (_("Changed system type of partition %d " + "to %x (%s)\n"), i + 1, sys, (temp = partition_type(sys)) ? temp : - "Unknown"); + _("Unknown")); changed[i] = 1; break; } @@ -1114,45 +1127,45 @@ static void check_consistency(struct partition *p, int partition) /* Same physical / logical beginning? */ if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) { - printf("Partition %d has different physical/logical " - "beginnings (non-Linux?):\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs); - printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs); + printf(_("Partition %d has different physical/logical " + "beginnings (non-Linux?):\n"), partition + 1); + printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs); + printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs); } /* Same physical / logical ending? */ if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) { - printf("Partition %d has different physical/logical " - "endings:\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pec, peh, pes); - printf("logical=(%d, %d, %d)\n",lec, leh, les); + printf(_("Partition %d has different physical/logical " + "endings:\n"), partition + 1); + printf(_(" phys=(%d, %d, %d) "), pec, peh, pes); + printf(_("logical=(%d, %d, %d)\n"),lec, leh, les); } #if 0 /* Beginning on cylinder boundary? */ if (pbh != !pbc || pbs != 1) { - printf("Partition %i does not start on cylinder " - "boundary:\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs); - printf("should be (%d, %d, 1)\n", pbc, !pbc); + printf(_("Partition %i does not start on cylinder " + "boundary:\n"), partition + 1); + printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs); + printf(_("should be (%d, %d, 1)\n"), pbc, !pbc); } #endif /* Ending on cylinder boundary? */ if (peh != (heads - 1) || pes != sectors) { - printf("Partition %i does not end on cylinder boundary:\n", + printf(_("Partition %i does not end on cylinder boundary:\n"), partition + 1); - printf(" phys=(%d, %d, %d) ", pec, peh, pes); - printf("should be (%d, %d, %d)\n", + printf(_(" phys=(%d, %d, %d) "), pec, peh, pes); + printf(_("should be (%d, %d, %d)\n"), pec, heads - 1, sectors); } } 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); + printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " + "%s of %d * %d bytes\n\n"), disk_device, heads, sectors, + cylinders, str_units(PLURAL), units_per_sector, sector_size); } void list_table(int xtra) @@ -1183,8 +1196,12 @@ void list_table(int xtra) if (w < 5) w = 5; - printf("%*s Boot Start End Blocks Id System\n", - (digit_last ? w + 2 : w + 1), "Device"); + + /* FIXME! let's see how this shows up with other languagues + acme@conectiva.com.br */ + + 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) { @@ -1209,7 +1226,7 @@ void list_table(int xtra) /* odd flag on end */ (long) pblocks, podd ? '+' : ' ', /* type id */ p->sys_ind, /* type name */ (type = partition_type(p->sys_ind)) ? - type : "Unknown"); + type : _("Unknown")); check_consistency(p, i); } } @@ -1224,9 +1241,9 @@ void x_list_table(int extend) q = ext_pointers; else q = part_table; - printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n", + printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"), disk_device, heads, sectors, cylinders); - printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"); + printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n")); for (i = 0 ; i < partitions; i++) if ((p = q[i]) != NULL) { printf("%2d %02x%4d%4d%5d%4d%4d%5d%8d%8d %02x\n", @@ -1265,21 +1282,21 @@ void check(int n, uint h, uint s, uint c, uint start) real_c = cylinder(s, c); total = (real_c * sectors + real_s) * heads + h; if (!total) - fprintf(stderr, "Warning: partition %d contains sector 0\n", n); + fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n); if (h >= heads) fprintf(stderr, - "Partition %d: head %d greater than maximum %d\n", + _("Partition %d: head %d greater than maximum %d\n"), n, h + 1, heads); if (real_s >= sectors) - fprintf(stderr, "Partition %d: sector %d greater than " - "maximum %d\n", n, s, sectors); + fprintf(stderr, _("Partition %d: sector %d greater than " + "maximum %d\n"), n, s, sectors); if (real_c >= cylinders) - fprintf(stderr, "Partitions %d: cylinder %d greater than " - "maximum %d\n", n, real_c + 1, cylinders); + fprintf(stderr, _("Partitions %d: cylinder %d greater than " + "maximum %d\n"), n, real_c + 1, cylinders); if (cylinders <= 1024 && start != total) fprintf(stderr, - "Partition %d: previous sectors %d disagrees with " - "total %d\n", n, start, total); + _("Partition %d: previous sectors %d disagrees with " + "total %d\n"), n, start, total); } @@ -1308,16 +1325,16 @@ void verify(void) if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { check_consistency(p, i); if (get_start_sect(p) + offsets[i] < first[i]) - printf("Warning: bad start-of-data in " - "partition %d\n", i + 1); + printf(_("Warning: bad start-of-data in " + "partition %d\n"), i + 1); check(i + 1, p->end_head, p->end_sector, p->end_cyl, last[i]); total += last[i] + 1 - first[i]; for (j = 0; j < i; j++) if ((first[i] >= first[j] && first[i] <= last[j]) || ((last[i] <= last[j] && last[i] >= first[j]))) { - printf("Warning: partition %d overlaps " - "partition %d.\n", j + 1, i + 1); + printf(_("Warning: partition %d overlaps " + "partition %d.\n"), j + 1, i + 1); total += first[i] >= first[j] ? first[i] : first[j]; total -= last[i] <= last[j] ? @@ -1334,21 +1351,21 @@ void verify(void) total++; if (!p->sys_ind) { if (i != 4 || i + 1 < partitions) - printf("Warning: partition %d " - "is empty\n", i + 1); + printf(_("Warning: partition %d " + "is empty\n"), i + 1); } else if (first[i] < extended_offset || last[i] > e_last) - printf("Logical partition %d not entirely in " - "partition %d\n", i + 1, ext_index + 1); + printf(_("Logical partition %d not entirely in " + "partition %d\n"), i + 1, ext_index + 1); } } if (total > heads * sectors * cylinders) - printf("Total allocated sectors %d greater than the maximum " - "%d\n", total, heads * sectors * cylinders); + printf(_("Total allocated sectors %d greater than the maximum " + "%d\n"), total, heads * sectors * cylinders); else if ((total = heads * sectors * cylinders - total) != 0) - printf("%d unallocated sectors\n", total); + printf(_("%d unallocated sectors\n"), total); } void add_partition(int n, int sys) @@ -1360,8 +1377,8 @@ void add_partition(int n, int sys) first[partitions], last[partitions]; if (p->sys_ind) { - printf("Partition %d is already defined. Delete " - "it before re-adding it.\n", n + 1); + printf(_("Partition %d is already defined. Delete " + "it before re-adding it.\n"), n + 1); return; } fill_bounds(first, last); @@ -1377,11 +1394,11 @@ void add_partition(int n, int sys) start = extended_offset + sector_offset; limit = get_start_sect(q) + get_nr_sects(q) - 1; } - if (unit_flag) + if (display_in_cyl_units) for (i = 0; i < partitions; i++) - first[i] = (cround(first[i]) - 1) * display_factor; + first[i] = (cround(first[i]) - 1) * units_per_sector; - sprintf(mesg, "First %s", str_units()); + sprintf(mesg, _("First %s"), str_units(SINGULAR)); do { temp = start; for (i = 0; i < partitions; i++) { @@ -1395,8 +1412,8 @@ void add_partition(int n, int sys) } if (start > limit) break; - if (start >= temp+display_factor && read) { - printf("Sector %d is already allocated\n", temp); + if (start >= temp+units_per_sector && read) { + printf(_("Sector %d is already allocated\n"), temp); temp = start; read = 0; } @@ -1405,15 +1422,21 @@ void add_partition(int n, int sys) i = start; start = read_int(cround(i), cround(i), cround(limit), 0, mesg); - if (unit_flag) { - start = (start - 1) * display_factor; + if (display_in_cyl_units) { + start = (start - 1) * units_per_sector; if (start < i) start = i; } read = 1; } } while (start != temp || !read); - if (n > 4) /* NOT for fifth partition */ + if (n > 4) { /* NOT for fifth partition */ offsets[n] = start - sector_offset; + if (offsets[n] == extended_offset) { /* must be corrected */ + offsets[n]++; + if (sector_offset == 1) + start++; + } + } for (i = 0; i < partitions; i++) { if (start < offsets[i] && limit >= offsets[i]) @@ -1422,22 +1445,22 @@ void add_partition(int n, int sys) limit = first[i] - 1; } if (start > limit) { - printf("No free sectors available\n"); + printf(_("No free sectors available\n")); if (n > 4) { free(buffers[n]); partitions--; } return; } - if (cround(start) == cround(limit)) - stop = start; - else { - sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", - str_units()); + if (cround(start) == cround(limit)) { + stop = limit; + } else { + sprintf(mesg, _("Last %s or +size or +sizeM or +sizeK"), + str_units(SINGULAR)); stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg); - if (unit_flag) { - stop = stop * display_factor - 1; + if (display_in_cyl_units) { + stop = stop * units_per_sector - 1; if (stop >limit) stop = limit; } @@ -1455,16 +1478,15 @@ void add_partition(int n, int sys) ext_pointers[4] = part_table[4] + 1; changed[4] = 1; partitions = 5; - } - else { + } else { if (n > 4) set_partition(n - 1, ext_pointers[n - 1], - start - sector_offset, stop, EXTENDED, + offsets[n], stop, EXTENDED, extended_offset); #if 0 if ((limit = get_nr_sects(p)) & 1) - printf("Warning: partition %d has an odd " - "number of sectors.\n", n + 1); + printf(_("Warning: partition %d has an odd " + "number of sectors.\n"), n + 1); #endif } } @@ -1500,7 +1522,7 @@ void new_partition(void) } if (partitions >= MAXIMUM_PARTS) { - printf("The maximum number of partitions has been created\n"); + printf(_("The maximum number of partitions has been created\n")); return; } @@ -1510,13 +1532,13 @@ void new_partition(void) if (extended_offset) add_logical(); else - printf("You must delete some partition and add " - "an extended partition first\n"); + printf(_("You must delete some partition and add " + "an extended partition first\n")); } else { char c, line[LINE_LENGTH]; - sprintf(line, "Command action\n %s\n p primary " - "partition (1-4)\n", extended_offset ? - "l logical (5 or over)" : "e extended"); + sprintf(line, _("Command action\n %s\n p primary " + "partition (1-4)\n"), extended_offset ? + _("l logical (5 or over)") : _("e extended")); while (1) if ((c = tolower(read_char(line))) == 'p') { add_partition(get_partition(0, 4), @@ -1533,8 +1555,8 @@ void new_partition(void) return; } else - printf("Invalid partition number " - "for type `%c'\n", c); + printf(_("Invalid partition number " + "for type `%c'\n"), c); } } @@ -1565,9 +1587,9 @@ void write_table(void) } } - printf("The partition table has been altered!\n\n"); + printf(_("The partition table has been altered!\n\n")); - printf("Calling ioctl() to re-read partition table.\n"); + printf(_("Calling ioctl() to re-read partition table.\n")); sync(); sleep(2); if ((i = ioctl(fd, BLKRRPART)) != 0) { @@ -1584,20 +1606,20 @@ void write_table(void) close(fd); - printf("Syncing disks.\n"); + printf(_("Syncing disks.\n")); sync(); sleep(4); /* for sync() */ if (i < 0) - printf("Re-read table failed with error %d: %s.\nReboot your " - "system to ensure the partition table is updated.\n", + printf(_("Re-read table failed with error %d: %s.\nReboot your " + "system to ensure the partition table is updated.\n"), error, strerror(error)); if (!sun_label && !sgi_label) printf( - "\nWARNING: If you have created or modified any DOS 6.x\n" + _("\nWARNING: If you have created or modified any DOS 6.x\n" "partitions, please see the fdisk manual page for additional\n" - "information.\n"); + "information.\n")); exit(0); } @@ -1626,7 +1648,7 @@ void print_raw(void) { int i; - printf("Device: %s\n", disk_device); + printf(_("Device: %s\n"), disk_device); if (sun_label || sgi_label) print_buffer(buffer); else for (i = 3; i < partitions; i++) @@ -1641,13 +1663,13 @@ void move_begin(int i) if (warn_geometry()) return; if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) { - printf("Partition %d has no data area\n", i + 1); + printf(_("Partition %d has no data area\n"), i + 1); return; } first = get_start_sect(p) + offsets[i]; new = read_int(first, first, get_start_sect(p) + get_nr_sects(p) + offsets[i] - 1, - first, "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; @@ -1661,7 +1683,7 @@ void xselect(void) { while(1) { putchar('\n'); - switch (tolower(read_char("Expert command (m for help): "))) { + switch (tolower(read_char(_("Expert command (m for help): ")))) { case 'a': if (sun_label) sun_set_alt_cyl(); @@ -1672,7 +1694,7 @@ void xselect(void) break; case 'c': cylinders = read_int(1, cylinders, 65535, - 0, "Number of cylinders"); + 0, _("Number of cylinders")); if (sun_label) sun_set_ncyl(cylinders); warn_cylinders(); @@ -1693,7 +1715,7 @@ void xselect(void) break; case 'h': heads = read_int(1, heads, 256, 0, - "Number of heads"); + _("Number of heads")); update_units(); break; case 'i': @@ -1712,17 +1734,18 @@ void xselect(void) break; case 'q': close(fd); + printf("\n"); exit(0); case 'r': return; case 's': sectors = read_int(1, sectors, 63, 0, - "Number of sectors"); + _("Number of sectors")); if (dos_compatible_flag) { sector_offset = sectors; - fprintf(stderr, "Warning: setting " + fprintf(stderr, _("Warning: setting " "sector offset for DOS " - "compatiblity\n"); + "compatiblity\n")); } update_units(); break; @@ -1782,8 +1805,8 @@ void try(char *device, int user_specified) list_disk_geometry(); if (btrydev(device) < 0) fprintf(stderr, - "Disk %s doesn't contain a valid " - "partition table\n", device); + _("Disk %s doesn't contain a valid " + "partition table\n"), device); close(fd); } else { close(fd); @@ -1796,39 +1819,52 @@ void try(char *device, int user_specified) and SCSI hard disks which may not be installed on the system. */ if(errno == EACCES) { - fprintf(stderr, "Cannot open %s\n", device); + fprintf(stderr, _("Cannot open %s\n"), device); return; } } } } +int +dir_exists(char *dirname) { + struct stat statbuf; + + return (stat(dirname, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)); +} + void dummy(int *kk) {} int main(int argc, char **argv) { - int i, j, s, c; + int j, c; int optl = 0, opts = 0; - char *part; + int user_set_sector_size = 0; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); /* * Calls: * fdisk -v - * fdisk -l [-b sectorsize] [-u] [device] ... + * fdisk -l [-b sectorsize] [-u] device ... * fdisk -s [partition] ... - * fdisk [-b sectorsize] [-u] [device] + * fdisk [-b sectorsize] [-u] device */ while ((c = getopt(argc, argv, "b:lsuv")) != EOF) { switch (c) { case 'b': + /* ugly: this sector size is really per device, + so cannot be combined with multiple disks */ sector_size = atoi(optarg); if (sector_size != 512 && sector_size != 1024 && sector_size != 2048) fatal(usage); sector_offset = 2; + user_set_sector_size = 1; break; case 'l': optl = 1; @@ -1837,7 +1873,7 @@ main(int argc, char **argv) opts = 1; break; case 'u': - unit_flag = 0; + display_in_cyl_units = 0; break; case 'v': printf("fdisk v" UTIL_LINUX_VERSION "\n"); @@ -1847,6 +1883,14 @@ main(int argc, char **argv) } } +#if 0 + printf(_("This kernel finds the sector size itself - -b option ignored\n")); +#else + if (user_set_sector_size && argc-optind != 1) + printf(_("Warning: the -b (set sector size) option should" + " be used with one specified device\n")); +#endif + if (optl) { listing = 1; nowarn = 1; @@ -1859,39 +1903,16 @@ main(int argc, char **argv) for(k=optind; k= partitions) - exit(1); -#if defined(sparc) - if (!sun_label) { - int id = sunlabel->infos[i].id; - - if (!(id > 1 && id != WHOLE_DISK)) - exit(1); - s = get_num_sectors(sunlabel->partitions[i]); - } else -#endif - s = get_nr_sects(part_table[i]); if (opts == 1) - printf("%d\n", s/2); + printf("%ld\n", size/2); else - printf("%s: %d\n", argv[j], s/2); + printf("%s: %ld\n", argv[j], size/2); } exit(0); } @@ -1947,17 +1938,14 @@ main(int argc, char **argv) disk_device = argv[optind]; else if (argc-optind != 0) fatal(usage); - else { - if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - printf("Using %s as default device!\n", disk_device); - } + else + fatal(usage2); + get_boot(fdisk); while (1) { putchar('\n'); - switch (tolower(read_char("Command (m for help): "))) { + switch (tolower(read_char(_("Command (m for help): ")))) { case 'a': if (sun_label) toggle_sunflags(get_partition(1, partitions), @@ -1971,11 +1959,11 @@ main(int argc, char **argv) break; case 'b': if (sgi_label) { - printf("\nThe current boot file is: %s\n", + 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"); + 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 @@ -2015,6 +2003,7 @@ main(int argc, char **argv) break; case 'q': close(fd); + printf("\n"); exit(0); case 's': create_sunlabel(); @@ -2034,8 +2023,8 @@ main(int argc, char **argv) case 'x': if( sgi_label ) { fprintf(stderr, - "\n\tSorry, no experts menu for SGI " - "partition tables available.\n\n"); + _("\n\tSorry, no experts menu for SGI " + "partition tables available.\n\n")); } else xselect(); break; diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h index 080515e5..ace1b0cd 100644 --- a/fdisk/fdisk.h +++ b/fdisk/fdisk.h @@ -21,7 +21,8 @@ #define SIZE(a) (sizeof(a)/sizeof((a)[0])) -#define cround(n) (((n) + display_factor * unit_flag) / display_factor) +#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n)) +#define scround(x) (((x)+units_per_sector-1)/units_per_sector) #if defined(__GNUC__) || defined(HAS_LONG_LONG) typedef long long ext2_loff_t; @@ -46,23 +47,19 @@ struct partition { unsigned char size4[4]; /* nr of sectors in partition */ }; -enum failure {usage, unable_to_open, unable_to_read, unable_to_seek, +enum failure {usage, usage2, ioctl_error, + unable_to_open, unable_to_read, unable_to_seek, unable_to_write, out_of_memory, no_partition, no_device}; enum action {fdisk, require, try_only, create_empty}; -struct systypes { - unsigned char index; - char *name; -}; - /* prototypes for fdisk.c */ extern char *disk_device, *line_ptr; extern int fd, partitions; -extern uint unit_flag, - display_factor; +extern uint display_in_cyl_units, + units_per_sector; extern struct partition *part_table[]; extern void fatal(enum failure why); extern int get_boot(enum action what); @@ -72,7 +69,10 @@ 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, uint base, char *mesg); -extern char *const str_units(void); + +#define PLURAL 0 +#define SINGULAR 1 +extern char *const str_units(int); extern unsigned int get_start_sect(struct partition *p); extern unsigned int get_nr_sects(struct partition *p); diff --git a/fdisk/fdiskaixlabel.c b/fdisk/fdiskaixlabel.c index 848a6ece..7540f9a6 100644 --- a/fdisk/fdiskaixlabel.c +++ b/fdisk/fdiskaixlabel.c @@ -1,3 +1,8 @@ +/* + Changes: + Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo + Internationalization +*/ #include /* stderr */ #include /* uint */ #include /* strstr */ @@ -5,8 +10,10 @@ #include +#include "common.h" #include "fdisk.h" #include "fdiskaixlabel.h" +#include "nls.h" static int other_endian = 0; static short volumes=1; @@ -18,8 +25,8 @@ static short volumes=1; void aix_info( void ) { - printf( - "\n\tThere is a valid AIX label on this disk.\n" + puts( + _("\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" @@ -29,7 +36,7 @@ aix_info( void ) "\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" + "\t machine. (Otherwise you become an AIXpert).") ); } diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c index 8edec233..64a79273 100644 --- a/fdisk/fdiskbsdlabel.c +++ b/fdisk/fdiskbsdlabel.c @@ -33,6 +33,9 @@ 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. + + Changes: + 19990319 - Arnaldo Carvalho de Melo - i18n/nls */ #include @@ -43,12 +46,14 @@ #include #include #include +#include "nls.h" #include #include #include /* for HDIO_GETGEO */ +#include "common.h" #include "fdisk.h" #define NETBSD_PARTITION 0xa5 #define DKTYPENAMES @@ -89,7 +94,7 @@ int btrydev (char * dev) { if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) return -1; - printf("\nBSD label for device: %s\n", dev); + printf(_("\nBSD label for device: %s\n"), dev); xbsd_print_disklabel (0); return 0; } @@ -97,25 +102,24 @@ btrydev (char * dev) { void bmenu (void) { - puts ("Command action\n" - " d delete a BSD partition\n" - " e edit drive data\n" - " i install bootstrap\n" - " l list known filesystem types\n" - " m print this menu\n" - " n add a new BSD partition\n" - " p print BSD partition table\n" - " q quit without saving changes\n" + puts (_("Command action")); + puts (_(" d delete a BSD partition")); + puts (_(" e edit drive data")); + puts (_(" i install bootstrap")); + puts (_(" l list known filesystem types")); + puts (_(" m print this menu")); + puts (_(" n add a new BSD partition")); + puts (_(" p print BSD partition table")); + puts (_(" q quit without saving changes")); #if defined (i386) || defined (sparc) - " r return to main menu\n" + puts (_(" r return to main menu")); #endif - " s show complete disklabel\n" - " t change a partition's filesystem id\n" - " w write disklabel to disk\n" + puts (_(" s show complete disklabel")); + puts (_(" t change a partition's filesystem id")); + puts (_(" w write disklabel to disk")); #if defined (i386) || defined (sparc) - " x link BSD partition to non-BSD partition" + puts (_(" x link BSD partition to non-BSD partition")); #endif - ); } int @@ -139,11 +143,11 @@ bselect (void) { xbsd_part_index = t; ss = get_start_sect(xbsd_part); if (ss == 0) { - fprintf (stderr, "Partition %s%d has invalid starting sector 0.\n", + fprintf (stderr, _("Partition %s%d has invalid starting sector 0.\n"), disk_device, t+1); return; } - printf ("Reading disklabel of %s%d at sector %d.\n", + printf (_("Reading disklabel of %s%d at sector %d.\n"), disk_device, t+1, ss + BSD_LABELSECTOR); if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0) if (xbsd_create_disklabel () == 0) @@ -152,7 +156,7 @@ bselect (void) { } if (t == 4) { - printf ("There is no *BSD partition on %s.\n", disk_device); + printf (_("There is no *BSD partition on %s.\n"), disk_device); return; } @@ -167,7 +171,7 @@ bselect (void) { while (1) { putchar ('\n'); - switch (tolower (read_char ("BSD disklabel command (m for help): "))) + switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) { case 'd': xbsd_delete_part (); @@ -245,18 +249,18 @@ xbsd_new_part (void) end = xbsd_dlabel.d_secperunit; #endif - sprintf (mesg, "First %s", str_units()); + sprintf (mesg, _("First %s"), str_units(SINGULAR)); begin = read_int (cround (begin), cround (begin), cround (end), 0, mesg); - sprintf (mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); + sprintf (mesg, _("Last %s or +size or +sizeM or +sizeK"), str_units(SINGULAR)); end = read_int (cround (begin), cround (end), cround (end), cround (begin), mesg); - if (unit_flag) + if (display_in_cyl_units) { - begin = (begin - 1) * display_factor; - end = end * display_factor - 1; + begin = (begin - 1) * units_per_sector; + end = end * units_per_sector - 1; } xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; xbsd_dlabel.d_partitions[i].p_offset = begin; @@ -279,33 +283,33 @@ xbsd_print_disklabel (int show_all) fprintf(f, "# %s:\n", disk_device); #endif if ((unsigned) lp->d_type < BSD_DKMAXTYPES) - fprintf(f, "type: %s\n", xbsd_dktypenames[lp->d_type]); + fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]); else - fprintf(f, "type: %d\n", lp->d_type); - fprintf(f, "disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename); - fprintf(f, "label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname); - fprintf(f, "flags:"); + fprintf(f, _("type: %d\n"), lp->d_type); + fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename); + fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname); + fprintf(f, _("flags:")); if (lp->d_flags & BSD_D_REMOVABLE) - fprintf(f, " removable"); + fprintf(f, _(" removable")); if (lp->d_flags & BSD_D_ECC) - fprintf(f, " ecc"); + fprintf(f, _(" ecc")); if (lp->d_flags & BSD_D_BADSECT) - fprintf(f, " badsect"); + fprintf(f, _(" badsect")); fprintf(f, "\n"); /* On various machines the fields of *lp are short/int/long */ /* In order to avoid problems, we cast them all to long. */ - fprintf(f, "bytes/sector: %ld\n", (long) lp->d_secsize); - fprintf(f, "sectors/track: %ld\n", (long) lp->d_nsectors); - fprintf(f, "tracks/cylinder: %ld\n", (long) lp->d_ntracks); - fprintf(f, "sectors/cylinder: %ld\n", (long) lp->d_secpercyl); - fprintf(f, "cylinders: %ld\n", (long) lp->d_ncylinders); - fprintf(f, "rpm: %d\n", lp->d_rpm); - fprintf(f, "interleave: %d\n", lp->d_interleave); - fprintf(f, "trackskew: %d\n", lp->d_trackskew); - fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); - fprintf(f, "headswitch: %ld\t\t# milliseconds\n", (long) lp->d_headswitch); - fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", (long) lp->d_trkseek); - fprintf(f, "drivedata: "); + fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize); + fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors); + fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks); + fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl); + fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders); + fprintf(f, _("rpm: %d\n"), lp->d_rpm); + fprintf(f, _("interleave: %d\n"), lp->d_interleave); + fprintf(f, _("trackskew: %d\n"), lp->d_trackskew); + fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew); + fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"), (long) lp->d_headswitch); + fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"), (long) lp->d_trkseek); + fprintf(f, _("drivedata: ")); for (i = NDDATA - 1; i >= 0; i--) if (lp->d_drivedata[i]) break; @@ -314,8 +318,8 @@ xbsd_print_disklabel (int show_all) for (j = 0; j <= i; j++) fprintf(f, "%ld ", (long) lp->d_drivedata[j]); } - fprintf (f, "\n%d partitions:\n", lp->d_npartitions); - fprintf (f, "# size offset fstype [fsize bsize cpg]\n"); + fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions); + fprintf (f, _("# size offset fstype [fsize bsize cpg]\n")); pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++) { if (pp->p_size) { @@ -371,10 +375,10 @@ static void xbsd_write_disklabel (void) { #if defined (i386) || defined (sparc) - printf ("Writing disklabel to %s%d.\n", disk_device, xbsd_part_index+1); + printf (_("Writing disklabel to %s%d.\n"), disk_device, xbsd_part_index+1); xbsd_writelabel (xbsd_part, &xbsd_dlabel); #elif defined (__alpha__) - printf ("Writing disklabel to %s.\n", disk_device); + printf (_("Writing disklabel to %s.\n"), disk_device); xbsd_writelabel (NULL, &xbsd_dlabel); #endif } @@ -385,14 +389,14 @@ xbsd_create_disklabel (void) char c; #if defined (i386) || defined (sparc) - fprintf (stderr, "%s%d contains no disklabel.\n", + fprintf (stderr, _("%s%d contains no disklabel.\n"), disk_device, xbsd_part_index+1); #elif defined (__alpha__) - fprintf (stderr, "%s contains no disklabel.\n", disk_device); + fprintf (stderr, _("%s contains no disklabel.\n"), disk_device); #endif while (1) - if ((c = tolower (read_char ("Do you want to create a disklabel? (y/n) "))) == 'y') + if ((c = tolower (read_char (_("Do you want to create a disklabel? (y/n) ")))) == 'y') { #if defined (i386) || defined (sparc) if (xbsd_initlabel (xbsd_part, &xbsd_dlabel, xbsd_part_index) == 1) @@ -431,28 +435,28 @@ xbsd_edit_disklabel (void) d = &xbsd_dlabel; #ifdef __alpha__ - d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,"bytes/sector"); - d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,"sectors/track"); - d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,"tracks/cylinder"); - d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,"cylinders"); + d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector")); + d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track")); + d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder")); + d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders")); #endif /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */ while (1) { d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks, - "sectors/cylinder"); + _("sectors/cylinder")); if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks) break; - printf ("Must be <= sectors/track * tracks/cylinder (default).\n"); + printf (_("Must be <= sectors/track * tracks/cylinder (default).\n")); } - d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,"rpm"); - d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,"interleave"); - d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,"trackskew"); - d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,"cylinderskew"); - d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,"headswitch"); - d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,"track-to-track seek"); + d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm")); + d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave")); + d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew")); + d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew")); + d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch")); + d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek")); d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; } @@ -493,7 +497,7 @@ xbsd_write_bootstrap (void) else dkbasename = "wd"; - printf ("Bootstrap: %sboot -> boot%s (%s): ", dkbasename, dkbasename, dkbasename); + printf (_("Bootstrap: %sboot -> boot%s (%s): "), dkbasename, dkbasename, dkbasename); if (read_line ()) { line_ptr[strlen (line_ptr)-1] = '\0'; @@ -519,7 +523,7 @@ xbsd_write_bootstrap (void) for (p=d; p < e; p++) if (*p) { - fprintf (stderr, "Bootstrap overlaps with disk label!\n"); + fprintf (stderr, _("Bootstrap overlaps with disk label!\n")); exit ( EXIT_FAILURE ); } @@ -540,9 +544,9 @@ xbsd_write_bootstrap (void) fatal (unable_to_write); #if defined (i386) || defined (sparc) - printf ("Bootstrap installed on %s%d.\n", disk_device, xbsd_part_index+1); + printf (_("Bootstrap installed on %s%d.\n"), disk_device, xbsd_part_index+1); #elif defined (__alpha__) - printf ("Bootstrap installed on %s.\n", disk_device); + printf (_("Bootstrap installed on %s.\n"), disk_device); #endif sync_disks (); @@ -563,7 +567,7 @@ xbsd_get_part_index (int max) char prompt[40]; char l; - sprintf (prompt, "Partition (a-%c): ", 'a' + max - 1); + sprintf (prompt, _("Partition (a-%c): "), 'a' + max - 1); do l = tolower (read_char (prompt)); while (l < 'a' || l > 'a' + max - 1); @@ -583,7 +587,7 @@ xbsd_check_new_partition (int *i) if (t == BSD_MAXPARTITIONS) { - fprintf (stderr, "The maximum number of partitions has been created\n"); + fprintf (stderr, _("The maximum number of partitions has been created\n")); return 0; } } @@ -594,7 +598,7 @@ xbsd_check_new_partition (int *i) if (xbsd_dlabel.d_partitions[*i].p_size != 0) { - fprintf (stderr, "This partition already exists.\n"); + fprintf (stderr, _("This partition already exists.\n")); return 0; } return 1; @@ -716,7 +720,7 @@ xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d) return 0; if (d -> d_npartitions > BSD_MAXPARTITIONS) - fprintf (stderr, "Warning: too many partitions (%d, maximum is %d).\n", + fprintf (stderr, _("Warning: too many partitions (%d, maximum is %d).\n"), d -> d_npartitions, BSD_MAXPARTITIONS); return 1; } @@ -762,7 +766,7 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) static void sync_disks (void) { - printf ("\nSyncing disks.\n"); + printf (_("\nSyncing disks.\n")); sync (); sleep (4); } diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c index 42f7363e..25ed31a3 100644 --- a/fdisk/fdisksgilabel.c +++ b/fdisk/fdisksgilabel.c @@ -5,6 +5,9 @@ * Copyright (C) Andreas Neuper, Sep 1998. * This file may be modified and redistributed under * the terms of the GNU Public License. + * + * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo + * Internationalization */ #include /* stderr */ #include /* uint */ @@ -15,9 +18,11 @@ #include /* assert */ #include +#include "nls.h" #include /* FLOPPY_MAJOR */ #include /* HDIO_GETGEO */ +#include "common.h" #include "fdisk.h" #include "fdisksgilabel.h" @@ -47,23 +52,22 @@ int isinfreelist( int b ) \ /* * 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"}, + {SGI_VOLHDR, N_("SGI volhdr")}, + {0x01, N_("SGI trkrepl")}, + {0x02, N_("SGI secrepl")}, + {SGI_SWAP, N_("SGI raw")}, + {0x04, N_("SGI bsd")}, + {0x05, N_("SGI sysv")}, + {ENTIRE_DISK, N_("SGI volume")}, + {SGI_EFS, N_("SGI efs")}, + {0x08, N_("SGI lvol")}, + {0x09, N_("SGI rlvol")}, + {0x0A, N_("SGI xfs")}, + {0x0B, N_("SGI xlvol")}, + {0x0C, N_("SGI rxlvol")}, + {LINUX_SWAP, N_("Linux swap")}, + {LINUX_NATIVE,N_("Linux native")}, {0, NULL } }; @@ -136,8 +140,8 @@ int check_sgi_label() { if (sizeof(sgilabel) > 512) { fprintf(stderr, - "According to MIPS Computer Systems, Inc the " - "Label must not contain more than 512 bytes\n"); + _("According to MIPS Computer Systems, Inc the " + "Label must not contain more than 512 bytes\n")); exit(1); } @@ -155,7 +159,7 @@ int check_sgi_label() if( two_s_complement_32bit_sum( (unsigned int*)sgilabel, sizeof(*sgilabel) ) ) { - fprintf( stderr, "Detected sgi disklabel with wrong checksum.\n" ); + fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n")); } else { heads = sgi_get_ntrks(); @@ -179,27 +183,28 @@ sgi_list_table( int xtra ) if( xtra ) { - printf( "\nDisk %s (SGI disk label): %d heads, %d sectors\n" + 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", + "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, SSWAP16(sgiparam.pcylcount), SSWAP16(sgiparam.sparecyl), SSWAP16(sgiparam.ilfact), (char *)sgilabel, - str_units(), display_factor); + str_units(PLURAL), units_per_sector); } else { - printf( "\nDisk %s (SGI disk label): %d heads, %d sectors, %d cylinders\n" - "Units = %ss of %d * 512 bytes\n\n", + printf( _("\nDisk %s (SGI disk label): " + "%d heads, %d sectors, %d cylinders\n" + "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, - str_units(), display_factor ); + str_units(PLURAL), units_per_sector ); } - printf("----- partitions -----\n" - "%*s Info Start End Sectors Id System\n", - w + 1, "Device"); + 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 ) @@ -216,12 +221,12 @@ sgi_list_table( int xtra ) /* no odd flag on end */ (long) len, /* type id */ sgi_get_sysid(i), /* type name */ (type = partition_type(sgi_get_sysid(i))) - ? type : "Unknown"); + ? type : _("Unknown")); } } - printf( "----- bootinfo -----\nBootfile: %s\n" - "----- directory entries -----\n", - sgilabel->boot_file ); + printf(_("----- bootinfo -----\nBootfile: %s\n" + "----- directory entries -----\n"), + sgilabel->boot_file ); for (i = 0 ; i < volumes; i++) { if (sgilabel->directory[i].vol_file_size) @@ -229,7 +234,7 @@ sgi_list_table( int xtra ) __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", + printf(_("%2d: %-10s sector%5u size%8u\n"), i, name, (unsigned int) start, (unsigned int) len); } } @@ -290,25 +295,25 @@ sgi_check_bootfile( const char* aFile ) { if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */ { - printf( "\nInvalid Bootfile!\n" + printf( _("\nInvalid Bootfile!\n" "\tThe bootfile must be an absolute non-zero pathname,\n" - "\te.g. \"/unix\" or \"/unix.save\".\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" ); + 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" ); + 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" ); + 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; } @@ -335,7 +340,7 @@ sgi_set_bootfile( const char* aFile ) sgilabel->boot_file[i] = 0; i++; } - printf( "\n\tBootfile is changed to \"%s\".\n", sgilabel->boot_file ); + printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file ); } return; } @@ -385,7 +390,7 @@ sgi_write_table( void ) static int -compare_start( int*x, int*y ) +compare_start( int *x, int *y ) { /* * sort according to start sectors @@ -423,7 +428,6 @@ 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 */ @@ -441,7 +445,7 @@ verify_sgi( int verbose ) if( entire++ == 1 ) { if(verbose) - printf("More than one entire disk entriy present.\n"); + printf(_("More than one entire disk entry present.\n")); } } } @@ -449,27 +453,27 @@ verify_sgi( int verbose ) if( sortcount == 0 ) { if(verbose) - printf("No partitions defined\n"); + 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" ); + 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] ) ); + 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", + 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" ); + 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 ); @@ -481,14 +485,14 @@ verify_sgi( int verbose ) { if(debug) /* I do not understand how some disks fulfil it */ if( verbose ) - printf( "Partition %d does not start on cylinder boundary.\n", + printf( _("Partition %d does not start on cylinder boundary.\n"), Index[i]+1 ); } if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 ) { if(debug) /* I do not understand how some disks fulfil it */ if( verbose ) - printf( "Partition %d does not end on cylinder boundary.\n", + printf( _("Partition %d does not end on cylinder boundary.\n"), Index[i]+1 ); } /* We cannot handle several "entire disk" entries. */ @@ -496,7 +500,7 @@ verify_sgi( int verbose ) if( start > sgi_get_start_sector( Index[i] ) ) { if( verbose ) - printf( "The Partition %d and %d overlap by %d sectors.\n", + 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; @@ -505,7 +509,7 @@ verify_sgi( int verbose ) if( start < sgi_get_start_sector( Index[i] ) ) { if( verbose ) - printf( "Unused gap of %8d sectors - sectors %8d-%d\n", + 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; @@ -525,7 +529,7 @@ verify_sgi( int verbose ) if( ( start < lastblock ) ) { if( verbose ) - printf( "Unused gap of %8d sectors - sectors %8d-%d\n", + printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"), lastblock - start, start, lastblock-1 ); gap += lastblock - start; add2freelist( start, lastblock ); @@ -538,20 +542,20 @@ verify_sgi( int verbose ) { if( !sgi_get_num_sectors( sgi_get_bootpartition() ) ) { - printf( "\nThe boot partition does not exist.\n" ); + printf( _("\nThe boot partition does not exist.\n") ); } if( !sgi_get_num_sectors( sgi_get_swappartition() ) ) { - printf( "\nThe swap partition does not exist.\n" ); + 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" ); + printf( _("\nThe swap partition has no swap type.\n") ); } if( sgi_check_bootfile( "/unix" ) ) { - printf( "\tYou have chosen an unusual boot file name.\n" ); + printf( _("\tYou have chosen an unusual boot file name.\n") ); } } return gap; @@ -562,18 +566,18 @@ 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"); + 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" + _("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" ); + "Type YES if you are sure about tagging this partition differently.\n")); if (strcmp (line_ptr, "YES\n")) return; } @@ -614,9 +618,7 @@ sgi_set_partition( int i, uint start, uint length, int sys ) 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" ); - } + printf(_("Do You know, You got a partition overlap on the disk?\n")); return; } @@ -679,38 +681,36 @@ sgi_add_partition( int n, int sys ) } if( sgi_get_num_sectors(n) ) { - printf( "Partition %d is already defined. Delete " - "it before re-adding it.\n", n + 1); + printf(_("Partition %d is already defined. Delete " + "it before re-adding it.\n"), n + 1); return; } if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) { - printf( "Attempting to generate entire disk entry automatically.\n" ); + printf(_("Attempting to generate entire disk entry automatically.\n")); sgi_set_entire(); sgi_set_volhdr(); } if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) { - printf( "The entire disk is already covered with partitions.\n" ); + printf(_("The entire disk is already covered with partitions.\n")); return; } if( sgi_gaps() < 0 ) { - printf( "You got a partition overlap on the disk. Fix it first!\n" ); + printf(_("You got a partition overlap on the disk. Fix it first!\n")); return; } - sprintf(mesg, "First %s", str_units()); - for(;;) - { - if(sys == SGI_VOLUME) - { + sprintf(mesg, _("First %s"), str_units(SINGULAR)); + for(;;) { + if(sys == SGI_VOLUME) { last = sgi_get_lastblock(); first = read_int(0, 0, last-1, 0, mesg); if( first != 0 ) { - printf( "It is highly recommended that eleventh partition\n" - "covers the entire disk and is of type `SGI volume'\n"); + printf(_("It is highly recommended that eleventh partition\n" + "covers the entire disk and is of type `SGI volume'\n")); } } else { first = freelist[0].first; @@ -718,30 +718,28 @@ sgi_add_partition( int n, int sys ) first = read_int(scround(first), scround(first), scround(last)-1, 0, mesg); } - if (unit_flag) - first *= display_factor; + if (display_in_cyl_units) + first *= units_per_sector; else first = first; /* align to cylinder if you know how ... */ if( !last ) last = isinfreelist(first); if( last == 0 ) { - printf( "You will get a partition overlap on the disk. " - "Fix it first!\n" ); + printf(_("You will get a partition overlap on the disk. " + "Fix it first!\n")); } else break; } - sprintf(mesg, " Last %s", str_units()); + sprintf(mesg, _(" Last %s"), str_units(SINGULAR)); last = read_int(scround(first), scround(last)-1, scround(last)-1, scround(first), mesg)+1; - if (unit_flag) - last *= display_factor; + if (display_in_cyl_units) + last *= units_per_sector; else last = last; /* align to cylinder if You know how ... */ if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) ) - { - printf( "It is highly recommended that eleventh partition\n" - "covers the entire disk and is of type `SGI volume'\n"); - } + printf(_("It is highly recommended that eleventh partition\n" + "covers the entire disk and is of type `SGI volume'\n")); sgi_set_partition( n, first, last-first, sys ); return; } @@ -755,9 +753,9 @@ create_sgilabel( void ) int sysid; } old[4]; int i=0; fprintf( stderr, - "Building a new SGI disklabel. Changes will remain in memory only,\n" + _("Building a new SGI disklabel. Changes will remain in memory only,\n" "until you decide to write them. After that, of course, the previous\n" - "content will be unrecoverable lost.\n\n"); + "content will be unrecoverable lost.\n\n")); #if BYTE_ORDER == LITTLE_ENDIAN other_endian = 1; #else @@ -783,9 +781,9 @@ create_sgilabel( void ) 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 ); + printf( _("Trying to keep parameters of partition %d.\n"), i ); if( debug ) - printf( "ID=%02x\tSTART=%d\tLENGTH=%d\n", + printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"), old[i].sysid, old[i].start, old[i].nsect ); } } diff --git a/fdisk/fdisksgilabel.h b/fdisk/fdisksgilabel.h index 6eb7293f..fa35f8f3 100644 --- a/fdisk/fdisksgilabel.h +++ b/fdisk/fdisksgilabel.h @@ -91,7 +91,6 @@ typedef struct { : (__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) diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index 70837737..d484e793 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -5,6 +5,9 @@ * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 * * Merged with fdisk for other architectures, aeb, June 1998. + * + * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo + * Internationalization */ #include /* stderr */ @@ -13,14 +16,19 @@ #include /* write */ #include /* ioctl */ #include /* stat */ +#include "nls.h" #include -#if 1 +#include "../defines.h" /* for HAVE_scsi_h */ +#ifdef HAVE_scsi_h +#define u_char unsigned char #include /* SCSI_IOCTL_GET_IDLUN */ +#undef u_char #endif #include /* FLOPPY_MAJOR */ #include /* HDIO_GETGEO */ +#include "common.h" #include "fdisk.h" #include "fdisksunlabel.h" @@ -32,17 +40,17 @@ static int floppy = 0; #define LINUX_NATIVE 0x83 struct systypes sun_sys_types[] = { - {0, "Empty"}, - {1, "Boot"}, - {2, "SunOS root"}, - {SUNOS_SWAP, "SunOS swap"}, - {4, "SunOS usr"}, - {WHOLE_DISK, "Whole disk"}, - {6, "SunOS stand"}, - {7, "SunOS var"}, - {8, "SunOS home"}, - {LINUX_SWAP, "Linux swap"}, - {LINUX_NATIVE, "Linux native"}, + {0, N_("Empty")}, + {1, N_("Boot")}, + {2, N_("SunOS root")}, + {SUNOS_SWAP, N_("SunOS swap")}, + {4, N_("SunOS usr")}, + {WHOLE_DISK, N_("Whole disk")}, + {6, N_("SunOS stand")}, + {7, N_("SunOS var")}, + {8, N_("SunOS home")}, + {LINUX_SWAP, N_("Linux swap")}, + {LINUX_NATIVE, N_("Linux native")}, { 0, NULL } }; @@ -111,10 +119,10 @@ int check_sun_label(void) ush = ((unsigned short *) (sunlabel + 1)) - 1; for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; if (csum) { - fprintf(stderr, "Detected sun disklabel with wrong checksum.\n" + fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n" "Probably you'll have to set all the values,\n" "e.g. heads, sectors, cylinders and partitions\n" - "or force a fresh label (s command in main menu)\n"); + "or force a fresh label (s command in main menu)\n")); } else { heads = SSWAP16(sunlabel->ntrks); cylinders = SSWAP16(sunlabel->ncyl); @@ -204,7 +212,7 @@ sun_autoconfigure_scsi() { 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); + 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; } @@ -230,9 +238,10 @@ void create_sunlabel(void) unsigned char c; struct sun_predefined_drives *p = NULL; - fprintf(stderr, "Building a new sun disklabel. Changes will remain in memory only,\n" - "until you decide to write them. After that, of course, the previous\n" - "content won't be recoverable.\n\n"); + fprintf(stderr, + _("Building a new sun disklabel. Changes will remain in memory only,\n" + "until you decide to write them. After that, of course, the previous\n" + "content won't be recoverable.\n\n")); #if BYTE_ORDER == LITTLE_ENDIAN other_endian = 1; #else @@ -241,9 +250,9 @@ void create_sunlabel(void) memset(buffer, 0, SECTOR_SIZE); sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC); if (!floppy) { - puts("Drive type\n" + puts(_("Drive type\n" " ? auto configure\n" - " 0 custom (with hardware detected defaults)"); + " 0 custom (with hardware detected defaults)")); for (i = 0; i < SIZE(sun_drives); i++) { printf(" %c %s%s%s\n", i + 'a', sun_drives[i].vendor, @@ -251,7 +260,7 @@ void create_sunlabel(void) sun_drives[i].model); } for (;;) { - c = read_char("Select type (? for auto, 0 for custom): "); + c = read_char(_("Select type (? for auto, 0 for custom): ")); if (c >= 'a' && c < 'a' + SIZE(sun_drives)) { p = sun_drives + c - 'a'; break; @@ -263,7 +272,7 @@ void create_sunlabel(void) } else if (c == '?' && scsi_disk) { p = sun_autoconfigure_scsi(); if (!p) - printf("Autoconfigure failed.\n"); + printf(_("Autoconfigure failed.\n")); else break; } @@ -290,26 +299,26 @@ void create_sunlabel(void) sunlabel->ilfact = SSWAP16(1); sunlabel->sparecyl = 0; } else { - heads = read_int(1,heads,1024,0,"Heads"); - sectors = read_int(1,sectors,1024,0,"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,0,"Cylinders"); + cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders")); else - cylinders = read_int(1,0,65535,0,"Cylinders"); + cylinders = read_int(1,0,65535,0,_("Cylinders")); sunlabel->nacyl = SSWAP16(read_int(0,2,65535,0, - "Alternate cylinders")); + _("Alternate cylinders"))); sunlabel->pcylcount = SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl), - 65535,0,"Physical cylinders")); + 65535,0,_("Physical cylinders"))); sunlabel->rspeed = SSWAP16(read_int(1,5400,100000,0, - "Rotation speed (rpm)")); + _("Rotation speed (rpm)"))); sunlabel->ilfact = - SSWAP16(read_int(1,1,32,0,"Interleave factor")); + SSWAP16(read_int(1,1,32,0,_("Interleave factor"))); sunlabel->sparecyl = SSWAP16(read_int(0,0,sectors,0, - "Extra sectors per cylinder")); + _("Extra sectors per cylinder"))); } } else { sunlabel->sparecyl = SSWAP16(p->sparecyl); @@ -322,10 +331,10 @@ void create_sunlabel(void) cylinders = p->ncyl; heads = p->ntrks; sectors = p->nsect; - puts("You may change all the disk params from the x menu"); + puts(_("You may change all the disk params from the x menu")); } sprintf(buffer, "%s%s%s cyl %d alt %d hd %d sec %d", - p ? p->vendor : "", (p && *p->vendor) ? " " : "", p ? p->model : (floppy ? "3,5\" floppy" : "Linux custom"), + p ? p->vendor : "", (p && *p->vendor) ? " " : "", p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")), cylinders, SSWAP16(sunlabel->nacyl), heads, sectors); sunlabel->ntrks = SSWAP16(heads); sunlabel->nsect = SSWAP16(sectors); @@ -406,7 +415,7 @@ void verify_sun(void) for (k = 0; k < 7; k++) { for (i = 0; i < 8; i++) { if (k && (lens[i] % (heads * sectors))) { - printf("Partition %d doesn't end on cylinder boundary\n", i+1); + printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1); } if (lens[i]) { for (j = 0; j < i; j++) @@ -426,8 +435,8 @@ void verify_sun(void) endo = starts[i]+lens[i]; if (starts[j]+lens[j] < endo) endo = starts[j]+lens[j]; - printf("Partition %d overlaps with others in " - "sectors %d-%d\n", i+1, starto, endo); + printf(_("Partition %d overlaps with others in " + "sectors %d-%d\n"), i+1, starto, endo); } } } @@ -443,18 +452,18 @@ void verify_sun(void) qsort(array,SIZE(array),sizeof(array[0]), (int (*)(const void *,const void *)) verify_sun_cmp); if (array[0] == -1) { - printf("No partitions defined\n"); + printf(_("No partitions defined\n")); return; } stop = cylinders * heads * sectors; if (starts[array[0]]) - printf("Unused gap - sectors 0-%d\n",starts[array[0]]); + printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]); for (i = 0; i < 7 && array[i+1] != -1; i++) { - printf("Unused gap - sectors %d-%d\n",starts[array[i]]+lens[array[i]],starts[array[i+1]]); + printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]); } start = starts[array[i]]+lens[array[i]]; if (start < stop) - printf("Unused gap - sectors %d-%d\n",start,stop); + printf(_("Unused gap - sectors %d-%d\n"),start,stop); } void add_sun_partition(int n, int sys) @@ -467,8 +476,8 @@ void add_sun_partition(int n, int sys) int i, first, last; if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { - printf("Partition %d is already defined. Delete " - "it before re-adding it.\n", n + 1); + printf(_("Partition %d is already defined. Delete " + "it before re-adding it.\n"), n + 1); return; } @@ -477,20 +486,20 @@ void add_sun_partition(int n, int sys) if (n == 2) whole_disk = 1; else { - printf("Other partitions already cover the whole disk.\nDelete " - "some/shrink them before retry.\n"); + printf(_("Other partitions already cover the whole disk.\nDelete " + "some/shrink them before retry.\n")); return; } } - sprintf(mesg, "First %s", str_units()); + sprintf(mesg, _("First %s"), str_units(SINGULAR)); for (;;) { if (whole_disk) first = read_int(0, 0, 0, 0, mesg); else first = read_int(scround(start), scround(stop)+1, scround(stop), 0, mesg); - if (unit_flag) - first *= display_factor; + if (display_in_cyl_units) + first *= units_per_sector; else /* Starting sector has to be properly aligned */ first = (first + heads * sectors - 1) / (heads * sectors); @@ -507,7 +516,7 @@ and is of type `Whole disk'\n"); whole_disk = 1; break; } - printf("Sector %d is already allocated\n", first); + printf(_("Sector %d is already allocated\n"), first); } else break; } @@ -517,7 +526,7 @@ and is of type `Whole disk'\n"); if (starts[i] > first && starts[i] < stop) stop = starts[i]; } - sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); + sprintf(mesg, _("Last %s or +size or +sizeM or +sizeK"), str_units(SINGULAR)); if (whole_disk) last = read_int(scround(stop2), scround(stop2), scround(stop2), 0, mesg); @@ -527,16 +536,19 @@ and is of type `Whole disk'\n"); else last = read_int(scround(first), scround(stop), scround(stop), scround(first), mesg); - if (unit_flag) - last *= display_factor; + if (display_in_cyl_units) + last *= units_per_sector; if (n == 2 && !first) { if (last >= stop2) { whole_disk = 1; last = stop2; } else if (last > stop) { - printf ("You haven't covered whole disk with 3rd partition, but your value\n" - "%d %s coveres some other partition. Your entry have been changed\n" - "to %d %s\n", scround(last), str_units(), scround(stop), str_units()); + printf ( + _("You haven't covered the whole disk with the 3rd partition, but your value\n" + "%d %s covers some other partition. Your entry has been changed\n" + "to %d %s\n"), + scround(last), str_units(SINGULAR), + scround(stop), str_units(SINGULAR)); last = stop; } } else if (!whole_disk && last > stop) @@ -552,10 +564,10 @@ sun_delete_partition(int i) { !sunlabel->partitions[i].start_cylinder && SSWAP32(sunlabel->partitions[i].num_sectors) == heads * sectors * cylinders) - printf("If you want to maintain SunOS/Solaris compatibility, " + 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", + "sectors\n"), (uint) SSWAP32(sunlabel->partitions[i].num_sectors)); sunlabel->infos[i].id = 0; sunlabel->partitions[i].num_sectors = 0; @@ -565,11 +577,11 @@ void sun_change_sysid(int i, int sys) { if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) { read_chars( - "It is highly recommended that the partition at offset 0\n" + _("It is highly recommended that the partition at offset 0\n" "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" "there may destroy your partition table and bootblock.\n" "Type YES if you're very sure you would like that partition\n" - "tagged with 82 (Linux swap): "); + "tagged with 82 (Linux swap): ")); if (strcmp (line_ptr, "YES\n")) return; } @@ -595,26 +607,28 @@ sun_list_table(int xtra) { w = strlen(disk_device); if (xtra) - printf("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" - "%d cylinders, %d alternate cylinders, %d physical cylinders\n" - "%d extra sects/cyl, interleave %d:1\n" - "%s\n" - "Units = %ss of %d * 512 bytes\n\n", + printf( + _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" + "%d cylinders, %d alternate cylinders, %d physical cylinders\n" + "%d extra sects/cyl, interleave %d:1\n" + "%s\n" + "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, SSWAP16(sunlabel->rspeed), cylinders, SSWAP16(sunlabel->nacyl), SSWAP16(sunlabel->pcylcount), SSWAP16(sunlabel->sparecyl), SSWAP16(sunlabel->ilfact), (char *)sunlabel, - str_units(), display_factor); + str_units(PLURAL), units_per_sector); else - printf("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" - "Units = %ss of %d * 512 bytes\n\n", + printf( + _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" + "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, - str_units(), display_factor); + str_units(PLURAL), units_per_sector); - printf("%*s Flag Start End Blocks Id System\n", - w + 1, "Device"); + 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; @@ -629,7 +643,7 @@ sun_list_table(int xtra) { /* 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"); + ? type : _("Unknown")); } } } @@ -638,7 +652,7 @@ void sun_set_alt_cyl(void) { sunlabel->nacyl = SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0, - "Number of alternate cylinders")); + _("Number of alternate cylinders"))); } void @@ -650,28 +664,28 @@ void sun_set_xcyl(void) { sunlabel->sparecyl = SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0, - "Extra sectors per cylinder")); + _("Extra sectors per cylinder"))); } void sun_set_ilfact(void) { sunlabel->ilfact = SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0, - "Interleave factor")); + _("Interleave factor"))); } void sun_set_rspeed(void) { sunlabel->rspeed = SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0, - "Rotation speed (rpm)")); + _("Rotation speed (rpm)"))); } void sun_set_pcylcount(void) { sunlabel->pcylcount = SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0, - "Number of physical cylinders")); + _("Number of physical cylinders"))); } void diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h index d9d3706d..1a75713c 100644 --- a/fdisk/fdisksunlabel.h +++ b/fdisk/fdisksunlabel.h @@ -36,8 +36,6 @@ typedef struct { #define SSWAP32(x) (other_endian ? __swap32(x) \ : (__u32)(x)) -#define scround(x) ((x+(display_factor-1)*unit_flag)/display_factor) - /* fdisk.c */ extern char changed[MAXIMUM_PARTS]; extern char buffer[MAX_SECTOR_SIZE]; diff --git a/fdisk/i386_sys_types.c b/fdisk/i386_sys_types.c new file mode 100644 index 00000000..f3624724 --- /dev/null +++ b/fdisk/i386_sys_types.c @@ -0,0 +1,86 @@ +/* DOS partition types */ +#include "common.h" +#include "nls.h" + +struct systypes i386_sys_types[] = { + {0x00, N_("Empty")}, + {0x01, N_("FAT12")}, + {0x02, N_("XENIX root")}, + {0x03, N_("XENIX usr")}, + {0x04, N_("FAT16 <32M")}, + {0x05, N_("Extended")}, /* DOS 3.3+ extended partition */ + {0x06, N_("FAT16")}, /* DOS 16-bit >=32M */ + {0x07, N_("HPFS/NTFS")}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ + {0x08, N_("AIX")}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ + {0x09, N_("AIX bootable")}, /* AIX data or Coherent */ + {0x0a, N_("OS/2 Boot Manager")},/* OS/2 Boot Manager */ + {0x0b, N_("Win95 FAT32")}, + {0x0c, N_("Win95 FAT32 (LBA)")},/* LBA really is `Extended Int 13h' */ + {0x0e, N_("Win95 FAT16 (LBA)")}, + {0x0f, N_("Win95 Ext'd (LBA)")}, + {0x10, N_("OPUS")}, + {0x11, N_("Hidden FAT12")}, + {0x12, N_("Compaq diagnostics")}, + {0x14, N_("Hidden FAT16 <32M")}, + {0x16, N_("Hidden FAT16")}, + {0x17, N_("Hidden HPFS/NTFS")}, + {0x18, N_("AST Windows swapfile")}, + {0x1b, N_("Hidden Win95 FAT32")}, + {0x1c, N_("Hidden Win95 FAT32 (LBA)")}, + {0x1e, N_("Hidden Win95 FAT16 (LBA)")}, + {0x24, N_("NEC DOS")}, + {0x3c, N_("PartitionMagic recovery")}, + {0x40, N_("Venix 80286")}, + {0x41, N_("PPC PReP Boot")}, + {0x42, N_("SFS")}, + {0x4d, N_("QNX4.x")}, + {0x4e, N_("QNX4.x 2nd part")}, + {0x4f, N_("QNX4.x 3rd part")}, + {0x50, N_("OnTrack DM")}, + {0x51, N_("OnTrack DM6 Aux1")}, /* (or Novell) */ + {0x52, N_("CP/M")}, /* CP/M or Microport SysV/AT */ + {0x53, N_("OnTrack DM6 Aux3")}, + {0x54, N_("OnTrackDM6")}, + {0x55, N_("EZ-Drive")}, + {0x56, N_("Golden Bow")}, + {0x5c, N_("Priam Edisk")}, + {0x61, N_("SpeedStor")}, + {0x63, N_("GNU HURD or SysV")}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ + {0x64, N_("Novell Netware 286")}, + {0x65, N_("Novell Netware 386")}, + {0x70, N_("DiskSecure Multi-Boot")}, + {0x75, N_("PC/IX")}, + {0x80, N_("Old Minix")}, /* Minix 1.4a and earlier */ + {0x81, N_("Minix / old Linux")},/* Minix 1.4b and later */ + {0x82, N_("Linux swap")}, /* also Solaris */ + {0x83, N_("Linux")}, + {0x84, N_("OS/2 hidden C: drive")}, + {0x85, N_("Linux extended")}, + {0x86, N_("NTFS volume set")}, + {0x87, N_("NTFS volume set")}, + {0x93, N_("Amoeba")}, + {0x94, N_("Amoeba BBT")}, /* (bad block table) */ + {0xa0, N_("IBM Thinkpad hibernation")}, + {0xa5, N_("BSD/386")}, + {0xa6, N_("OpenBSD")}, + {0xa7, N_("NeXTSTEP")}, + {0xb7, N_("BSDI fs")}, + {0xb8, N_("BSDI swap")}, + {0xc1, N_("DRDOS/sec (FAT-12)")}, + {0xc4, N_("DRDOS/sec (FAT-16 < 32M)")}, + {0xc6, N_("DRDOS/sec (FAT-16)")}, + {0xc7, N_("Syrinx")}, + {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ + {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT extended partition */ + {0xe3, N_("DOS R/O")}, /* DOS R/O or SpeedStor */ + {0xe4, N_("SpeedStor")}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ + {0xeb, N_("BeOS fs")}, + {0xf1, N_("SpeedStor")}, + {0xf4, N_("SpeedStor")}, /* SpeedStor large partition */ + {0xf2, N_("DOS secondary")}, /* DOS 3.3+ secondary */ + {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition with autodetect + using persistent superblock */ + {0xfe, N_("LANstep")}, /* SpeedStor >1024 cyl. or LANstep */ + {0xff, N_("BBT")}, /* Xenix Bad Block Table */ + { 0, 0 } +}; diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c index c3f470f8..d25543dd 100644 --- a/fdisk/sfdisk.c +++ b/fdisk/sfdisk.c @@ -25,6 +25,9 @@ * Well, a good user interface is still lacking. On the other hand, * many configurations cannot be handled by any other fdisk. * I changed the name to sfdisk to prevent confusion. - aeb, 970501 + * + * Changes: + * 19990319 - Arnaldo Carvalho de Melo - i18n */ #define PROGNAME "sfdisk" @@ -45,6 +48,9 @@ #include /* _syscall */ #include /* HDIO_GETGEO */ #include /* BLKGETSIZE */ +#include +#include "nls.h" +#include "common.h" #define SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -139,12 +145,12 @@ sseek(char *dev, unsigned int fd, unsigned long s) { if ((out = lseek(fd, in, SEEK_SET)) != in) { #endif perror("llseek"); - error("seek error on %s - cannot seek to %lu\n", dev, s); + error(_("seek error on %s - cannot seek to %lu\n"), dev, s); return 0; } if (in != out) { - error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", + error(_("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n"), (uint)(in>>32), (uint)(in & 0xffffffff), (uint)(out>>32), (uint)(out & 0xffffffff)); return 0; @@ -190,11 +196,11 @@ get_sector(char *dev, int fd, unsigned long sno) { return 0; if (!(s = (struct sector *) malloc(sizeof(struct sector)))) - fatal("out of memory - giving up\n"); + fatal(_("out of memory - giving up\n")); if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { perror("read"); - error("read error on %s - cannot read sector %lu\n", dev, sno); + error(_("read error on %s - cannot read sector %lu\n"), dev, sno); free(s); return 0; } @@ -210,7 +216,7 @@ get_sector(char *dev, int fd, unsigned long sno) { int msdos_signature (struct sector *s) { if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) { - error("ERROR: sector %lu does not have an msdos signature\n", + error(_("ERROR: sector %lu does not have an msdos signature\n"), s->sectornumber); return 0; } @@ -227,7 +233,7 @@ write_sectors(char *dev, int fd) { return 0; if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { perror("write"); - error("write error on %s - cannot write sector %lu\n", + error(_("write error on %s - cannot write sector %lu\n"), dev, s->sectornumber); return 0; } @@ -265,7 +271,7 @@ save_sectors(char *dev, int fdin) { fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444); if (fdout < 0) { perror(save_sector_file); - error("cannot open partition sector save file (%s)\n", + error(_("cannot open partition sector save file (%s)\n"), save_sector_file); return 0; } @@ -277,13 +283,13 @@ save_sectors(char *dev, int fdin) { return 0; if (read(fdin, ss+4, 512) != 512) { perror("read"); - error("read error on %s - cannot read sector %lu\n", + error(_("read error on %s - cannot read sector %lu\n"), dev, s->sectornumber); return 0; } if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) { perror("write"); - error("write error on %s\n", save_sector_file); + error(_("write error on %s\n"), save_sector_file); return 0; } } @@ -301,35 +307,35 @@ restore_sectors(char *dev) { if (stat(restore_sector_file, &statbuf) < 0) { perror(restore_sector_file); - error("cannot stat partition restore file (%s)\n", + error(_("cannot stat partition restore file (%s)\n"), restore_sector_file); return 0; } if (statbuf.st_size % 516) { - error("partition restore file has wrong size - not restoring\n"); + error(_("partition restore file has wrong size - not restoring\n")); return 0; } if (!(ss = (char *) malloc(statbuf.st_size))) { - error("out of memory?\n"); + error(_("out of memory?\n")); return 0; } fdin = open(restore_sector_file, O_RDONLY); if (fdin < 0) { perror(restore_sector_file); - error("cannot open partition restore file (%s)\n", + error(_("cannot open partition restore file (%s)\n"), restore_sector_file); return 0; } if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) { perror("read"); - error("error reading %s\n", restore_sector_file); + error(_("error reading %s\n"), restore_sector_file); return 0; } fdout = open(dev, O_WRONLY); if (fdout < 0) { perror(dev); - error("cannot open device %s for writing\n", dev); + error(_("cannot open device %s for writing\n"), dev); return 0; } @@ -341,7 +347,7 @@ restore_sectors(char *dev) { return 0; if (write(fdout, ss+4, 512) != 512) { perror(dev); - error("error writing sector %lu on %s\n", sno, dev); + error(_("error writing sector %lu on %s\n"), sno, dev); return 0; } ss += 516; @@ -367,61 +373,70 @@ restore_sectors(char *dev) { * }; */ -unsigned long cylindersize; -unsigned long heads, sectors, cylinders; -unsigned long specified_heads, specified_sectors, specified_cylinders; +/* + * We consider several geometries for a disk: + * B - the BIOS geometry, gotten from the kernel via HDIO_GETGEO + * F - the fdisk geometry + * U - the user-specified geometry + * + * 0 means unspecified / unknown + */ +struct geometry { + unsigned long cylindersize; + unsigned long heads, sectors, cylinders; +} B, F, U; void get_cylindersize(char *dev, int fd, int silent) { struct hd_geometry g; int ioctl_ok = 0; - heads = sectors = cylinders = 0; + B.heads = B.sectors = B.cylinders = 0; if (!ioctl(fd, HDIO_GETGEO, &g)) { ioctl_ok = 1; - heads = g.heads; - sectors = g.sectors; - cylinders = g.cylinders; + B.heads = g.heads; + B.sectors = g.sectors; + B.cylinders = g.cylinders; } - if (specified_heads) - heads = specified_heads; - if (specified_sectors) - sectors = specified_sectors; - if (specified_cylinders) - cylinders = specified_cylinders; + if (U.heads) + B.heads = U.heads; + if (U.sectors) + B.sectors = U.sectors; + if (U.cylinders) + B.cylinders = U.cylinders; - cylindersize = heads * sectors; + B.cylindersize = B.heads * B.sectors; if (ioctl_ok) { if (g.start && !force) { warn( - "Warning: start=%d - this looks like a partition rather than\n" + _("Warning: start=%d - this looks like a partition rather than\n" "the entire disk. Using fdisk on it is probably meaningless.\n" - "[Use the --force option if you really want this]\n", g.start); + "[Use the --force option if you really want this]\n"), g.start); exit(1); } - if (heads != g.heads) - warn("Warning: HDIO_GETGEO says that there are %d heads\n", + if (B.heads != g.heads) + warn(_("Warning: HDIO_GETGEO says that there are %d heads\n"), g.heads); - if (sectors != g.sectors) - warn("Warning: HDIO_GETGEO says that there are %d sectors\n", + if (B.sectors != g.sectors) + warn(_("Warning: HDIO_GETGEO says that there are %d sectors\n"), g.sectors); - if (cylinders != g.cylinders) - warn("Warning: HDIO_GETGEO says that there are %d cylinders\n", + if (B.cylinders != g.cylinders) + warn(_("Warning: HDIO_GETGEO says that there are %d cylinders\n"), g.cylinders); } else if (!silent) - if (!heads || !sectors || !cylinders) - printf("Disk %s: cannot get geometry\n", dev); - if (sectors > 63) - warn("Warning: unlikely number of sectors (%d) - usually at most 63\n" - "This will give problems with all software that uses C/H/S addressing.\n", - sectors); + if (!B.heads || !B.sectors || !B.cylinders) + printf(_("Disk %s: cannot get geometry\n"), dev); + if (B.sectors > 63) + warn(_("Warning: unlikely number of sectors (%d) - usually at most 63\n" + "This will give problems with all software that uses C/H/S addressing.\n"), + B.sectors); if (!silent) - printf("\nDisk %s: %lu heads, %lu sectors, %lu cylinders\n", - dev, heads, sectors, cylinders); + printf(_("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n"), + dev, B.cylinders, B.heads, B.sectors); } typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */ @@ -431,19 +446,19 @@ typedef struct { unsigned long h,s,c; } longchs; longchs zero_longchs; chs -longchs_to_chs (longchs aa) { +longchs_to_chs (longchs aa, struct geometry G) { chs a; if (aa.h < 256 && aa.s < 64 && aa.c < 1024) { a.h = aa.h; a.s = aa.s | ((aa.c >> 2) & 0xc0); a.c = (aa.c & 0xff); - } else if (heads && sectors) { - a.h = heads - 1; - a.s = sectors | 0xc0; + } else if (G.heads && G.sectors) { + a.h = G.heads - 1; + a.s = G.sectors | 0xc0; a.c = 0xff; } else - a = zero_chs; + a = zero_chs; return a; } @@ -459,13 +474,13 @@ chs_to_longchs (chs a) { } longchs -ulong_to_longchs (unsigned long sno) { +ulong_to_longchs (unsigned long sno, struct geometry G) { longchs aa; - if (heads && sectors && cylindersize) { - aa.s = 1 + sno % sectors; - aa.h = (sno / sectors) % heads; - aa.c = sno / cylindersize; + if (G.heads && G.sectors && G.cylindersize) { + aa.s = 1 + sno % G.sectors; + aa.h = (sno / G.sectors) % G.heads; + aa.c = sno / G.cylindersize; return aa; } else { return zero_longchs; @@ -473,18 +488,18 @@ ulong_to_longchs (unsigned long sno) { } unsigned long -longchs_to_ulong (longchs aa) { - return (aa.c*cylindersize + aa.h*sectors + aa.s - 1); +longchs_to_ulong (longchs aa, struct geometry G) { + return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1); } chs -ulong_to_chs (unsigned long sno) { - return longchs_to_chs(ulong_to_longchs(sno)); +ulong_to_chs (unsigned long sno, struct geometry G) { + return longchs_to_chs(ulong_to_longchs(sno, G), G); } unsigned long -chs_to_ulong (chs a) { - return longchs_to_ulong(chs_to_longchs(a)); +chs_to_ulong (chs a, struct geometry G) { + return longchs_to_ulong(chs_to_longchs(a), G); } int @@ -499,19 +514,19 @@ chs_ok (chs a, char *v, char *w) { if (is_equal_chs(a, zero_chs)) return 1; - if (heads && aa.h >= heads) { - warn("%s of partition %s has impossible value for head: " - "%d (should be in 0-%d)\n", w, v, aa.h, heads-1); + if (B.heads && aa.h >= B.heads) { + warn(_("%s of partition %s has impossible value for head: " + "%d (should be in 0-%d)\n"), w, v, aa.h, B.heads-1); ret = 0; } - if (sectors && (aa.s == 0 || aa.s > sectors)) { - warn("%s of partition %s has impossible value for sector: " - "%d (should be in 1-%d)\n", w, v, aa.s, sectors); + if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { + warn(_("%s of partition %s has impossible value for sector: " + "%d (should be in 1-%d)\n"), w, v, aa.s, B.sectors); ret = 0; } - if (cylinders && aa.c >= cylinders) { - warn("%s of partition %s has impossible value for cylinders: " - "%d (should be in 0-%d)\n", w, v, aa.c, cylinders-1); + if (B.cylinders && aa.c >= B.cylinders) { + warn(_("%s of partition %s has impossible value for cylinders: " + "%d (should be in 0-%d)\n"), w, v, aa.c, B.cylinders-1); ret = 0; } return ret; @@ -533,109 +548,25 @@ chs_ok (chs a, char *v, char *w) { #define LINUX_EXTENDED 0x85 #define BSD_PARTITION 0xa5 -/* - * List of system Id's, adapted from fdisk 2.0d and - * and SFS and several other sources. - */ -struct systypes { - unsigned char type; - char *name; -} sys_types[] = { - {0, "Empty"}, - {1, "DOS 12-bit FAT"}, /* Primary DOS with 12-bit FAT */ - {2, "XENIX /"}, /* XENIX / filesystem */ - {3, "XENIX /usr"}, /* XENIX /usr filesystem */ - {4, "DOS 16-bit FAT <32M"}, /* Primary DOS with 16-bit FAT */ - {5, "DOS Extended"}, /* DOS 3.3+ extended partition */ - {6, "DOS 16-bit FAT >=32M"}, - {7, "HPFS / NTFS"}, - {8, "AIX boot or SplitDrive"}, - {9, "AIX data or Coherent"}, - {0x0a, "OS/2 Boot Manager"}, - {0x0b, "Win95 FAT32"}, - {0x0c, "Win95 FAT32 (LBA)"}, - {0x0e, "Win95 FAT16 (LBA)"}, - {0x0f, "Win95 Extended (LBA)"}, - {0x10, "OPUS"}, - {0x11, "Hidden DOS FAT12"}, - {0x12, "Compaq diagnostics"}, - {0x14, "Hidden DOS FAT16"}, - {0x16, "Hidden DOS FAT16 (big)"}, - {0x17, "Hidden HPFS/NTFS"}, - {0x18, "AST Windows swapfile"}, - {0x24, "NEC DOS"}, - {0x3c, "PartitionMagic recovery"}, - {0x40, "Venix 80286"}, - {0x41, "Linux/MINIX (sharing disk with DRDOS)"}, - {0x42, "SFS or Linux swap (sharing disk with DRDOS)"}, - {0x43, "Linux native (sharing disk with DRDOS)"}, - {0x50, "DM (disk manager)"}, - {0x51, "DM6 Aux1 (or Novell)"}, - {0x52, "CP/M or Microport SysV/AT"}, - {0x53, "DM6 Aux3"}, - {0x54, "DM6"}, - {0x55, "EZ-Drive (disk manager)"}, - {0x56, "Golden Bow (disk manager)"}, - {0x5c, "Priam Edisk (disk manager)"}, - {0x61, "SpeedStor"}, - {0x63, "GNU HURD or Mach or Sys V/386 (such as ISC UNIX)"}, - {0x64, "Novell Netware 286"}, - {0x65, "Novell Netware 386"}, - {0x70, "DiskSecure Multi-Boot"}, - {0x75, "PC/IX"}, - {0x77, "QNX4.x"}, - {0x78, "QNX4.x 2nd part"}, - {0x79, "QNX4.x 3rd part"}, - {0x80, "MINIX until 1.4a"}, - {0x81, "MINIX / old Linux"}, - {0x82, "Linux swap"}, - {0x83, "Linux native"}, - {0x84, "OS/2 hidden C: drive"}, - {0x85, "Linux extended"}, - {0x86, "NTFS volume set"}, - {0x87, "NTFS volume set"}, - {0x93, "Amoeba"}, - {0x94, "Amoeba BBT"}, /* (bad block table) */ - {0xa0, "IBM Thinkpad hibernation"}, /* according to dan@fch.wimsey.bc.ca */ - {0xa5, "BSD/386"}, /* 386BSD */ - {0xa6, "OpenBSD"}, - {0xa7, "NeXTSTEP 486"}, - {0xb7, "BSDI fs"}, - {0xb8, "BSDI swap"}, - {0xc1, "DRDOS/sec (FAT-12)"}, - {0xc4, "DRDOS/sec (FAT-16, < 32M)"}, - {0xc6, "DRDOS/sec (FAT-16, >= 32M)"}, - {0xc7, "Syrinx"}, - {0xdb, "CP/M or Concurrent CP/M or Concurrent DOS or CTOS"}, - {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"}, - {0xfe, "SpeedStor >1024 cyl. or LANstep"}, - {0xff, "Xenix Bad Block Table"} -}; - +/* List of partition types now in i386_sys_types.c */ const char * sysname(unsigned char type) { struct systypes *s; - for (s = sys_types; s - sys_types < SIZE(sys_types); s++) + for (s = i386_sys_types; s->name; s++) if (s->type == type) - return s->name; - return "Unknown"; + return _(s->name); + return _("Unknown"); } void list_types(void) { struct systypes *s; - printf("Id Name\n\n"); - for (s = sys_types; s - sys_types < SIZE(sys_types); s++) - printf("%2x %s\n", s->type, s->name); + printf(_("Id Name\n\n")); + for (s = i386_sys_types; s->name; s++) + printf("%2x %s\n", s->type, _(s->name)); } int @@ -767,7 +698,8 @@ add_sector_and_offset(struct disk_desc *z) { } /* tell the kernel to reread the partition tables */ -int reread_ioctl(int fd) { +int +reread_ioctl(int fd) { if(ioctl(fd, BLKRRPART)) { perror("BLKRRPART"); return -1; @@ -775,21 +707,28 @@ int reread_ioctl(int fd) { return 0; } +int +is_blockdev(int fd) { + struct stat statbuf; + + return(fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)); +} + /* reread after writing */ void reread_disk_partition(char *dev, int fd) { - printf("Re-reading the partition table ...\n"); + printf(_("Re-reading the partition table ...\n")); fflush(stdout); sync(); sleep(3); /* superfluous since 1.3.20 */ - if(reread_ioctl(fd)) - printf("The command to re-read the partition table failed\n" - "Reboot your system now, before using mkfs\n"); + if(reread_ioctl(fd) && is_blockdev(fd)) + printf(_("The command to re-read the partition table failed\n" + "Reboot your system now, before using mkfs\n")); if (close(fd)) { perror(dev); - printf("Error closing %s\n", dev); + printf(_("Error closing %s\n"), dev); } printf("\n"); } @@ -827,7 +766,7 @@ asc_to_index(char *pnam, struct disk_desc *z) { pno = linux_to_index(pnum, z); } if (!(pno >= 0 && pno < z->partno)) - fatal("%s: no such partition\n", pnam); + fatal(_("%s: no such partition\n"), pnam); return pno; } @@ -850,7 +789,7 @@ void set_format(char c) { switch(c) { default: - printf("unrecognized format - using sectors\n"); + printf(_("unrecognized format - using sectors\n")); case 'S': specified_format = F_SECTOR; break; case 'B': specified_format = F_BLOCK; break; case 'C': specified_format = F_CYLINDER; break; @@ -860,14 +799,15 @@ set_format(char c) { unsigned long unitsize(int format) { - default_format = (cylindersize ? F_CYLINDER : F_MEGABYTE); + default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE); if (!format && !(format = specified_format)) format = default_format; switch(format) { default: case F_CYLINDER: - if(cylindersize) return cylindersize; + if(B.cylindersize) + return B.cylindersize; case F_SECTOR: return 1; case F_BLOCK: @@ -879,51 +819,51 @@ unitsize(int format) { unsigned long get_disksize(int format) { - unsigned long cs = cylinders; + unsigned long cs = B.cylinders; if (cs && leave_last) cs--; - return (cs * cylindersize) / unitsize(format); + return (cs * B.cylindersize) / unitsize(format); } void -out_partition_header(char *dev, int format) { +out_partition_header(char *dev, int format, struct geometry G) { if (dump) { - printf("# partition table of %s\n", dev); - printf("unit: sectors\n\n"); + printf(_("# partition table of %s\n"), dev); + printf(_("unit: sectors\n\n")); return; } - default_format = (cylindersize ? F_CYLINDER : F_MEGABYTE); + default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE); if (!format && !(format = specified_format)) format = default_format; switch(format) { default: - printf("unimplemented format - using %s\n", - cylindersize ? "cylinders" : "sectors"); + printf(_("unimplemented format - using %s\n"), + G.cylindersize ? _("cylinders") : _("sectors")); case F_CYLINDER: - if (cylindersize) { - printf("Units = cylinders of %lu bytes, blocks of 1024 bytes" - ", counting from %d\n\n", - cylindersize<<9, increment); - printf(" Device Boot Start End #cyls #blocks Id System\n"); + if (G.cylindersize) { + printf(_("Units = cylinders of %lu bytes, blocks of 1024 bytes" + ", counting from %d\n\n"), + G.cylindersize<<9, increment); + printf(_(" Device Boot Start End #cyls #blocks Id System\n")); break; } /* fall through */ case F_SECTOR: - printf("Units = sectors of 512 bytes, counting from %d\n\n", + printf(_("Units = sectors of 512 bytes, counting from %d\n\n"), increment); - printf(" Device Boot Start End #sectors Id System\n"); + printf(_(" Device Boot Start End #sectors Id System\n")); break; case F_BLOCK: - printf("Units = blocks of 1024 bytes, counting from %d\n\n", + printf(_("Units = blocks of 1024 bytes, counting from %d\n\n"), increment); - printf(" Device Boot Start End #blocks Id System\n"); + printf(_(" Device Boot Start End #blocks Id System\n")); break; case F_MEGABYTE: - printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" - ", counting from %d\n\n", increment); - printf(" Device Boot Start End MB #blocks Id System\n"); + printf(_("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" + ", counting from %d\n\n"), increment); + printf(_(" Device Boot Start End MB #blocks Id System\n")); break; } } @@ -955,8 +895,19 @@ out_roundup_size(int width, unsigned long n, unsigned long unit) { putchar(' '); } +int +get_fdisk_geometry(struct part_desc *p) { + chs b = p->p.end_chs; + longchs bb = chs_to_longchs(b); + F.heads = bb.h+1; + F.sectors = bb.s; + F.cylindersize = F.heads*F.sectors; + return (F.sectors != B.sectors || F.heads != B.heads); +} + void -out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { +out_partition(char *dev, int format, struct part_desc *p, + struct disk_desc *z, struct geometry G) { unsigned long start, end, size; int pno, lpno; @@ -978,12 +929,12 @@ out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { size = p->size; if (dump) { - printf(" start=%9lu", start); - printf(", size=%8lu", size); + printf(_(" start=%9lu"), start); + printf(_(", size=%8lu"), size); if (p->ptype == DOS_TYPE) { - printf(", Id=%2x", p->p.sys_type); + printf(_(", Id=%2x"), p->p.sys_type); if (p->p.bootable == 0x80) - printf(", bootable"); + printf(_(", bootable")); } printf("\n"); return; @@ -998,10 +949,10 @@ out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { switch(format) { case F_CYLINDER: - if (cylindersize) { - out_rounddown(6, start, cylindersize, increment); - out_roundup(6, end, cylindersize, increment); - out_roundup_size(6, size, cylindersize); + if (G.cylindersize) { + out_rounddown(6, start, G.cylindersize, increment); + out_roundup(6, end, G.cylindersize, increment); + out_roundup_size(6, size, G.cylindersize); out_rounddown(8, size, 2, 0); break; } @@ -1039,22 +990,22 @@ out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { if (!quiet && p->ptype == DOS_TYPE) { chs a, b; longchs aa, bb; - a = (size ? ulong_to_chs(start) : zero_chs); + a = (size ? ulong_to_chs(start,G) : zero_chs); b = p->p.begin_chs; aa = chs_to_longchs(a); bb = chs_to_longchs(b); if(a.s && !is_equal_chs(a, b)) - printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + printf(_("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n"), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - a = (size ? ulong_to_chs(end) : zero_chs); + a = (size ? ulong_to_chs(end,G) : zero_chs); b = p->p.end_chs; aa = chs_to_longchs(a); bb = chs_to_longchs(b); if(a.s && !is_equal_chs(a, b)) - printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + printf(_("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n"), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - if(cylinders && cylinders < 1024 && bb.c > cylinders) - printf("partition ends on cylinder %ld, beyond the end of the disk\n", + if(G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders) + printf(_("partition ends on cylinder %ld, beyond the end of the disk\n"), bb.c); } } @@ -1064,11 +1015,16 @@ out_partitions(char *dev, struct disk_desc *z) { int pno, format = 0; if (z->partno == 0) - printf("No partitions found\n"); + printf(_("No partitions found\n")); else { - out_partition_header(dev, format); + if (get_fdisk_geometry(&(z->partitions[0]))) + printf(_("Warning: The first partition looks like it was made\n" + " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n" + "For this listing I'll assume that geometry.\n"), + F.heads, F.sectors, B.cylinders, B.heads, B.sectors); + out_partition_header(dev, format, F); for(pno=0; pno < z->partno; pno++) { - out_partition(dev, format, &(z->partitions[pno]), z); + out_partition(dev, format, &(z->partitions[pno]), z, F); if(show_extended && pno%4==3) printf("\n"); } @@ -1109,9 +1065,9 @@ partitions_ok(struct disk_desc *z) { /* Have at least 4 partitions been defined? */ if (partno < 4) { if (!partno) - fatal("no partition table present.\n"); + fatal(_("no partition table present.\n")); else - fatal("strange, only %d partitions defined.\n", partno); + fatal(_("strange, only %d partitions defined.\n"), partno); return 0; } @@ -1120,13 +1076,13 @@ partitions_ok(struct disk_desc *z) { for (p = partitions; p - partitions < partno; p++) if (p->size == 0) { if(p->p.sys_type != EMPTY_PARTITION) - warn("Warning: partition %s has size 0 but is not marked Empty\n", + warn(_("Warning: partition %s has size 0 but is not marked Empty\n"), PNO(p)); else if(p->p.bootable != 0) - warn("Warning: partition %s has size 0 and is bootable\n", + warn(_("Warning: partition %s has size 0 and is bootable\n"), PNO(p)); else if(p->p.start_sect != 0) - warn("Warning: partition %s has size 0 and nonzero start\n", + warn(_("Warning: partition %s has size 0 and nonzero start\n"), PNO(p)); /* all this is probably harmless, no error return */ } @@ -1137,8 +1093,8 @@ partitions_ok(struct disk_desc *z) { if (p->size && !is_extended(p->p.sys_type)) { q = p->ep; if (p->start < q->start || p->start + p->size > q->start + q->size) { - warn("Warning: partition %s ", PNO(p)); - warn("is not contained in partition %s\n", PNO(q)); + warn(_("Warning: partition %s "), PNO(p)); + warn(_("is not contained in partition %s\n"), PNO(q)); return 0; } } @@ -1149,8 +1105,8 @@ partitions_ok(struct disk_desc *z) { for (q = p+1; q < partitions+partno; q++) if (q->size && !is_extended(q->p.sys_type)) if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) { - warn("Warning: partitions %s ", PNO(p)); - warn("and %s overlap\n", PNO(q)); + warn(_("Warning: partitions %s "), PNO(p)); + warn(_("and %s overlap\n"), PNO(q)); return 0; } @@ -1161,9 +1117,9 @@ partitions_ok(struct disk_desc *z) { for (q = partitions; q < partitions+partno; q++) if (is_extended(q->p.sys_type)) if (p->start <= q->start && p->start + p->size > q->start) { - warn("Warning: partition %s contains part of ", PNO(p)); - warn("the partition table (sector %lu),\n", q->start); - warn("and will destroy it when filled\n"); + warn(_("Warning: partition %s contains part of "), PNO(p)); + warn(_("the partition table (sector %lu),\n"), q->start); + warn(_("and will destroy it when filled\n")); return 0; } @@ -1172,11 +1128,11 @@ partitions_ok(struct disk_desc *z) { for (p = partitions; p < partitions+partno; p++) if (p->size) { if(p->start == 0) { - warn("Warning: partition %s starts at sector 0\n", PNO(p)); + warn(_("Warning: partition %s starts at sector 0\n"), PNO(p)); return 0; } if (p->size && p->start + p->size > ds) { - warn("Warning: partition %s extends past end of disk\n", PNO(p)); + warn(_("Warning: partition %s extends past end of disk\n"), PNO(p)); return 0; } } @@ -1190,8 +1146,8 @@ partitions_ok(struct disk_desc *z) { if (p->p.sys_type == EXTENDED_PARTITION) ect++; if (ect > 1 && !Linux) { - warn("Among the primary partitions, at most one can be extended\n"); - warn(" (although this is not a problem under Linux)\n"); + warn(_("Among the primary partitions, at most one can be extended\n")); + warn(_(" (although this is not a problem under Linux)\n")); return 0; } } @@ -1202,20 +1158,20 @@ partitions_ok(struct disk_desc *z) { * The first partition starts after MBR. * Logical partitions start slightly after the containing extended partn. */ - if (cylindersize) { + if (B.cylindersize) { for(p = partitions; p < partitions+partno; p++) if (p->size) { - if(p->start % cylindersize != 0 - && (!p->ep || p->start / cylindersize != p->ep->start / cylindersize) - && (p->p.start_sect >= cylindersize)) { - warn("Warning: partition %s does not start " - "at a cylinder boundary\n", PNO(p)); + if(p->start % B.cylindersize != 0 + && (!p->ep || p->start / B.cylindersize != p->ep->start / B.cylindersize) + && (p->p.start_sect >= B.cylindersize)) { + warn(_("Warning: partition %s does not start " + "at a cylinder boundary\n"), PNO(p)); if (!Linux) return 0; } - if((p->start + p->size) % cylindersize) { - warn("Warning: partition %s does not end " - "at a cylinder boundary\n", PNO(p)); + if((p->start + p->size) % B.cylindersize) { + warn(_("Warning: partition %s does not end " + "at a cylinder boundary\n"), PNO(p)); if (!Linux) return 0; } @@ -1232,22 +1188,22 @@ partitions_ok(struct disk_desc *z) { if (pno == -1) pno = p - partitions; else if (p - partitions < 4) { - warn("Warning: more than one primary partition is marked " + warn(_("Warning: more than one primary partition is marked " "bootable (active)\n" "This does not matter for LILO, but the DOS MBR will " - "not boot this disk.\n"); + "not boot this disk.\n")); break; } if (p - partitions >= 4) { - warn("Warning: usually one can boot from primary partitions " - "only\n" "LILO disregards the `bootable' flag.\n"); + warn(_("Warning: usually one can boot from primary partitions " + "only\nLILO disregards the `bootable' flag.\n")); break; } } if (pno == -1 || pno >= 4) - warn("Warning: no primary partition is marked bootable (active)\n" + warn(_("Warning: no primary partition is marked bootable (active)\n" "This does not matter for LILO, but the DOS MBR will " - "not boot this disk.\n"); + "not boot this disk.\n")); } /* Is chs as we expect? */ @@ -1255,26 +1211,26 @@ partitions_ok(struct disk_desc *z) { if(p->ptype == DOS_TYPE) { chs a, b; longchs aa, bb; - a = p->size ? ulong_to_chs(p->start) : zero_chs; + a = p->size ? ulong_to_chs(p->start,B) : zero_chs; b = p->p.begin_chs; aa = chs_to_longchs(a); bb = chs_to_longchs(b); if (!chs_ok(b, PNO(p), "start")) return 0; if(a.s && !is_equal_chs(a, b)) - warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + warn(_("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n"), PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - a = p->size ? ulong_to_chs(p->start + p->size - 1) : zero_chs; + a = p->size ? ulong_to_chs(p->start + p->size - 1, B) : zero_chs; b = p->p.end_chs; aa = chs_to_longchs(a); bb = chs_to_longchs(b); if (!chs_ok(b, PNO(p), "end")) return 0; if(a.s && !is_equal_chs(a, b)) - warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + warn(_("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n"), PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - if(cylinders && cylinders < 1024 && bb.c > cylinders) - warn("partition %s ends on cylinder %ld, beyond the end of the disk\n", + if(B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders) + warn(_("partition %s ends on cylinder %ld, beyond the end of the disk\n"), PNO(p), bb.c); } @@ -1307,7 +1263,7 @@ extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) cp = s->data + 0x1be; if (pno+4 >= SIZE(z->partitions)) { - printf("too many partitions - ignoring those past nr (%d)\n", + printf(_("too many partitions - ignoring those past nr (%d)\n"), pno-1); break; } @@ -1320,9 +1276,11 @@ extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) partitions[pno].ep = ep; copy_to_part(cp,&p); if (is_extended(p.sys_type)) { + partitions[pno].start = start + p.start_sect; if (next) - printf("tree of partitions?\n"); - partitions[pno].start = next = start + p.start_sect; + printf(_("tree of partitions?\n")); + else + next = partitions[pno].start; /* follow `upper' branch */ moretodo = 1; } else { partitions[pno].start = here + p.start_sect; @@ -1382,8 +1340,8 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { bp = bp0 = &l->d_partitions[0]; while (bp - bp0 <= BSD_MAXPARTITIONS) { if (pno+1 >= SIZE(z->partitions)) { - printf("too many partitions - ignoring those " - "past nr (%d)\n", pno-1); + printf(_("too many partitions - ignoring those " + "past nr (%d)\n"), pno-1); break; } if (bp->p_fstype != BSD_FS_UNUSED) { @@ -1424,14 +1382,14 @@ msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { || pt.sys_type == EZD_PARTITION || pt.sys_type == DM6_AUX1PARTITION || pt.sys_type == DM6_AUX3PARTITION) { - printf("detected Disk Manager - unable to handle that\n"); + printf(_("detected Disk Manager - unable to handle that\n")); return 0; } { unsigned int sig = *(unsigned short *)(s->data + 2); if (sig <= 0x1ae && *(unsigned short *)(s->data + sig) == 0x55aa && (1 & *(unsigned char *)(s->data + sig + 2))) { - printf("DM6 signature found - giving up\n"); + printf(_("DM6 signature found - giving up\n")); return 0; } } @@ -1451,14 +1409,14 @@ msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { for (i=0; i<4; i++) { if (is_extended(partitions[i].p.sys_type)) { if (!partitions[i].size) { - printf("strange..., an extended partition of size 0?\n"); + printf(_("strange..., an extended partition of size 0?\n")); continue; } extended_partition(dev, fd, &partitions[i], z); } if (is_bsd(partitions[i].p.sys_type)) { if (!partitions[i].size) { - printf("strange..., a BSD partition of size 0?\n"); + printf(_("strange..., a BSD partition of size 0?\n")); continue; } bsd_partition(dev, fd, &partitions[i], z); @@ -1490,7 +1448,7 @@ get_partitions(char *dev, int fd, struct disk_desc *z) { && !osf_partition(dev, fd, 0, z) && !sun_partition(dev, fd, 0, z) && !amiga_partition(dev, fd, 0, z)) { - printf(" %s: unrecognized partition\n", dev); + printf(_(" %s: unrecognized partition\n"), dev); return; } } @@ -1502,7 +1460,7 @@ write_partitions(char *dev, int fd, struct disk_desc *z) { int pno = z->partno; if (no_write) { - printf("-n flag was given: Nothing changed\n"); + printf(_("-n flag was given: Nothing changed\n")); exit(0); } @@ -1515,12 +1473,12 @@ write_partitions(char *dev, int fd, struct disk_desc *z) { } if (save_sector_file) { if (!save_sectors(dev, fd)) { - fatal("Failed saving the old sectors - aborting\n"); + fatal(_("Failed saving the old sectors - aborting\n")); return 0; } } if (!write_sectors(dev, fd)) { - error("Failed writing the partition on %s\n", dev); + error(_("Failed writing the partition on %s\n"), dev); return 0; } return 1; @@ -1597,7 +1555,7 @@ read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int line return RD_EOF; } if (!(lp = index(lp, '\n'))) - fatal("long or incomplete input line - quitting\n"); + fatal(_("long or incomplete input line - quitting\n")); *lp = 0; /* remove comments, if any */ @@ -1633,20 +1591,20 @@ read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int line while(isalnum(*ip)) /* 0x07FF */ ip++; } else - fatal("input error: `=' expected after %s field\n", + fatal(_("input error: `=' expected after %s field\n"), d->fldname); if (fno <= d->fldno) fno = d->fldno + 1; if(*ip == 0) return fno; if(*ip != ',' && *ip != ';') - fatal("input error: unexpected character %c after %s field\n", + fatal(_("input error: unexpected character %c after %s field\n"), *ip, d->fldname); *ip = 0; goto nxtfld; } } - fatal("unrecognized input: %s\n", ip); + fatal(_("unrecognized input: %s\n"), ip); } /* split line into fields */ @@ -1678,11 +1636,11 @@ get_ul(char *u, unsigned long *up, unsigned long def, int base) { errno = 0; *up = strtoul(u, &nu, base); if (errno == ERANGE) { - printf("number too big\n"); + printf(_("number too big\n")); return -1; } if (*nu) { - printf("trailing junk after number\n"); + printf(_("trailing junk after number\n")); return -1; } } else @@ -1783,7 +1741,7 @@ max_length(int pno, int is_extended, struct part_desc *ep, int format, int compute_start_sect(struct part_desc *p, struct part_desc *ep) { unsigned long base; - int inc = (DOS && sectors) ? sectors : 1; + int inc = (DOS && B.sectors) ? B.sectors : 1; int delta; if (ep && p->start + p->size >= ep->start + 1) @@ -1798,7 +1756,7 @@ compute_start_sect(struct part_desc *p, struct part_desc *ep) { if (is_extended(p->p.sys_type) && boxes == ONESECTOR) p->size = inc; else if ((int)(p->size) <= 0) { - warn("no room for partition descriptor\n"); + warn(_("no room for partition descriptor\n")); return 0; } } @@ -1812,8 +1770,8 @@ compute_start_sect(struct part_desc *p, struct part_desc *ep) { p->p.end_chs = zero_chs; } else { p->p.start_sect = p->start - base; - p->p.begin_chs = ulong_to_chs(p->start); - p->p.end_chs = ulong_to_chs(p->start + p->size - 1); + p->p.begin_chs = ulong_to_chs(p->start,B); + p->p.end_chs = ulong_to_chs(p->start + p->size - 1,B); } p->p.nr_sects = p->size; return 1; @@ -1823,7 +1781,7 @@ compute_start_sect(struct part_desc *p, struct part_desc *ep) { int build_surrounding_extended(struct part_desc *p, struct part_desc *ep, struct disk_desc *z) { - int inc = (DOS && sectors) ? sectors : 1; + int inc = (DOS && B.sectors) ? B.sectors : 1; int format = F_SECTOR; struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep; @@ -1831,7 +1789,7 @@ build_surrounding_extended(struct part_desc *p, struct part_desc *ep, ep->start = first_free(ep-p0, 1, eep, format, p->start, z); ep->size = max_length(ep-p0, 1, eep, format, ep->start, z); if (ep->start > p->start || ep->start + ep->size < p->start + p->size) { - warn("cannot build surrounding extended partition\n"); + warn(_("cannot build surrounding extended partition\n")); return 0; } } else { @@ -1882,7 +1840,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, if (fno == RD_EOF) { return -1; } else if (fno > 10 && *(fields[10]) != 0) { - printf("too many input fields\n"); + printf(_("too many input fields\n")); return 0; } @@ -1893,7 +1851,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, /* use specified format, but round to cylinders if F_MEGABYTE specified */ format = 0; - if (cylindersize && specified_format == F_MEGABYTE) + if (B.cylindersize && specified_format == F_MEGABYTE) format = F_CYLINDER; orig = (one_only ? &(oldp.partitions[pno]) : 0); @@ -1916,7 +1874,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, } if (ml == 0 && pno >= 4) { /* no free blocks left - don't read any further */ - warn("No room for more\n"); + warn(_("No room for more\n")); return -1; } } @@ -1935,7 +1893,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16)) return 0; if (ul > 255) { - warn("Illegal type\n"); + warn(_("Illegal type\n")); return 0; } p.p.sys_type = ul; @@ -1967,12 +1925,12 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, p.size -= (p.size % unitsize(format)); } if (p.size > ml1) { - warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0)); + warn(_("Warning: exceeds max allowable size (%lu)\n"), ml1 / unitsize(0)); if (!force) return 0; } if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) { - warn("Warning: empty partition\n"); + warn(_("Warning: empty partition\n")); if (!force) return 0; } @@ -1986,7 +1944,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, } if (p.start < ff1 && p.size > 0) { - warn("Warning: bad partition start (earliest %lu)\n", + warn(_("Warning: bad partition start (earliest %lu)\n"), (ff1 + unitsize(0) - 1) / unitsize(0)); if (!force) return 0; @@ -1999,7 +1957,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+")) ul = 0x80; else { - warn("unrecognized bootable flag - choose - or *\n"); + warn(_("unrecognized bootable flag - choose - or *\n")); return 0; } p.p.bootable = ul; @@ -2016,31 +1974,31 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, if (fno < 5) { bb = aa; } else if (fno < 7) { - warn("partial c,h,s specification?\n"); + warn(_("partial c,h,s specification?\n")); return 0; } else if(get_ul(fields[4], &bb.c, aa.c, 0) || get_ul(fields[5], &bb.h, aa.h, 0) || get_ul(fields[6], &bb.s, aa.s, 0)) return 0; - p.p.begin_chs = longchs_to_chs(bb); + p.p.begin_chs = longchs_to_chs(bb,B); } { longchs aa = chs_to_longchs(p.p.end_chs), bb; if (fno < 8) { bb = aa; } else if (fno < 10) { - warn("partial c,h,s specification?\n"); + warn(_("partial c,h,s specification?\n")); return 0; } else if(get_ul(fields[7], &bb.c, aa.c, 0) || get_ul(fields[8], &bb.h, aa.h, 0) || get_ul(fields[9], &bb.s, aa.s, 0)) return 0; - p.p.end_chs = longchs_to_chs(bb); + p.p.end_chs = longchs_to_chs(bb, B); } if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION && (is_extended(p.p.sys_type) != (pct == 1))) { - warn("Extended partition not where expected\n"); + warn(_("Extended partition not where expected\n")); if (!force) return 0; } @@ -2050,7 +2008,7 @@ read_line(int pno, struct part_desc *ep, char *dev, int interactive, z->partno += 4; /* reqd for out_partition() */ if (interactive) - out_partition(dev, 0, &(z->partitions[pno]), z); + out_partition(dev, 0, &(z->partitions[pno]), z, B); return 1; } @@ -2072,7 +2030,7 @@ read_partition(char *dev, int interactive, int pno, struct part_desc *ep, while (!(i = read_line(pno, ep, dev, interactive, z))) if (!interactive) - fatal("bad input\n"); + fatal(_("bad input\n")); if (i < 0) { p->ep = ep; return 0; @@ -2094,7 +2052,7 @@ read_partition_chain(char *dev, int interactive, struct part_desc *ep, while (1) { base = z->partno; if (base+4 > SIZE(z->partitions)) { - printf("too many partitions\n"); + printf(_("too many partitions\n")); break; } for (i=0; i<4; i++) @@ -2127,11 +2085,9 @@ read_input(char *dev, int interactive, struct disk_desc *z) { z->partno = 0; if (interactive) - warn(" -Input in the following format; absent fields get a default value. - -Usually you only need to specify and (and perhaps ). -"); + warn(_("Input in the following format; absent fields get a default value.\n" + " \n" + "Usually you only need to specify and (and perhaps ).\n")); eof = 0; for (i=0; i<4; i++) @@ -2149,54 +2105,51 @@ Usually you only need to specify and (and perhaps ). */ static void version(void) { - printf(PROGNAME " version " VERSION " (aeb@cwi.nl, " DATE ")\n"); + printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, _("version"), VERSION, DATE); } static void usage(void) { version(); - printf("Usage: - " PROGNAME " [options] device ... -device: something like /dev/hda or /dev/sda -useful options: - -s [or --show-size]: list size of a partition - -c [or --id]: print or change partition Id - -l [or --list]: list partitions of each device - -d [or --dump]: idem, but in a format suitable for later input - -i [or --increment]: number cylinders etc. from 1 instead of from 0 - -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB - -T [or --list-types]:list the known partition types - -D [or --DOS]: for DOS-compatibility: waste a little space - -R [or --re-read]: make kernel reread partition table - -N# : change only the partition with number # - -n : do not actually write to disk - -O file : save the sectors that will be overwritten to file - -I file : restore these sectors again - -v [or --version]: print version - -? [or --help]: print this message -dangerous options: - -g [or --show-geometry]: print the kernel's idea of the geometry - -x [or --show-extended]: also list extended partitions on output - or expect descriptors for them on input - -L [or --Linux]: do not complain about things irrelevant for Linux - -q [or --quiet]: suppress warning messages - You can override the detected geometry using: - -C# [or --cylinders #]:set the number of cylinders to use - -H# [or --heads #]: set the number of heads to use - -S# [or --sectors #]: set the number of sectors to use - You can disable all consistency checking with: - -f [or --force]: do what I say, even if it is stupid -"); + printf(_("Usage: %s [options] device ...\n"), PROGNAME); + puts (_("device: something like /dev/hda or /dev/sda")); + puts (_("useful options:")); + puts (_(" -s [or --show-size]: list size of a partition")); + puts (_(" -c [or --id]: print or change partition Id")); + puts (_(" -l [or --list]: list partitions of each device")); + puts (_(" -d [or --dump]: idem, but in a format suitable for later input")); + puts (_(" -i [or --increment]: number cylinders etc. from 1 instead of from 0")); + puts (_(" -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB")); + puts (_(" -T [or --list-types]:list the known partition types")); + puts (_(" -D [or --DOS]: for DOS-compatibility: waste a little space")); + puts (_(" -R [or --re-read]: make kernel reread partition table")); + puts (_(" -N# : change only the partition with number #")); + puts (_(" -n : do not actually write to disk")); + puts (_(" -O file : save the sectors that will be overwritten to file")); + puts (_(" -I file : restore these sectors again")); + puts (_(" -v [or --version]: print version")); + puts (_(" -? [or --help]: print this message")); + puts (_("dangerous options:")); + puts (_(" -g [or --show-geometry]: print the kernel's idea of the geometry")); + puts (_(" -x [or --show-extended]: also list extended partitions on output\n" + " or expect descriptors for them on input")); + puts (_(" -L [or --Linux]: do not complain about things irrelevant for Linux")); + puts (_(" -q [or --quiet]: suppress warning messages")); + puts (_(" You can override the detected geometry using:")); + puts (_(" -C# [or --cylinders #]:set the number of cylinders to use")); + puts (_(" -H# [or --heads #]: set the number of heads to use")); + puts (_(" -S# [or --sectors #]: set the number of sectors to use")); + puts (_("You can disable all consistency checking with:")); + puts (_(" -f [or --force]: do what I say, even if it is stupid")); exit(1); } static void activate_usage(char *progn) { - printf("Usage: - %s device list active partitions on device - %s device n1 n2 ... activate partitions n1 ..., inactivate the rest - %s device activate partition n, inactivate the other ones -", progn, progn, PROGNAME " -An"); + puts (_("Usage:")); + printf(_("%s device list active partitions on device\n"), progn); + printf(_("%s device n1 n2 ... activate partitions n1 ..., inactivate the rest\n"), progn); + printf(_("%s -An device activate partition n, inactivate the other ones\n"), PROGNAME); exit(1); } @@ -2310,8 +2263,12 @@ main(int argc, char **argv) { char *activatearg = 0; char *unhidearg = 0; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + if (argc < 1) - fatal("no command?\n"); + fatal(_("no command?\n")); if ((progn = rindex(argv[0], '/')) == NULL) progn = argv[0]; else @@ -2358,11 +2315,11 @@ main(int argc, char **argv) { activatearg = optarg; activate = 1; break; case 'C': - specified_cylinders = atoi(optarg); break; + U.cylinders = atoi(optarg); break; case 'D': DOS = 1; break; case 'H': - specified_heads = atoi(optarg); break; + U.heads = atoi(optarg); break; case 'L': Linux = 1; break; case 'N': @@ -2374,7 +2331,7 @@ main(int argc, char **argv) { case 'R': opt_reread = 1; break; case 'S': - specified_sectors = atoi(optarg); break; + U.sectors = atoi(optarg); break; case 'T': list_types(); exit(0); @@ -2434,7 +2391,7 @@ main(int argc, char **argv) { } if (opt_size) - printf("total: %d blocks\n", total_size); + printf(_("total: %d blocks\n"), total_size); exit(exit_status); } @@ -2471,18 +2428,18 @@ main(int argc, char **argv) { } if (do_id) { if ((do_id & PRINT_ID) != 0 && optind != argc-2) - fatal("usage: sfdisk --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: sfdisk --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: sfdisk --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); } if (optind != argc-1) - fatal("can specify only one device (except with -l or -s)\n"); + fatal(_("can specify only one device (except with -l or -s)\n")); dev = argv[optind]; if (opt_reread) @@ -2507,7 +2464,7 @@ my_open (char *dev, int rw, int silent) { fd = open(dev, mode); if (fd < 0 && !silent) { perror(dev); - fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading"); + fatal(_("cannot open %s %s\n"), dev, rw ? _("read-write") : _("for reading")); } return fd; } @@ -2532,7 +2489,7 @@ do_list (char *dev, int silent) { if (verify) { if (partitions_ok(z)) - warn("%s: OK\n", dev); + warn(_("%s: OK\n"), dev); else exit_status = 1; } @@ -2549,16 +2506,17 @@ do_geom (char *dev, int silent) { /* get_cylindersize(dev, fd, silent); */ if (!ioctl(fd, HDIO_GETGEO, &g)) - printf("%s: %d cylinders, %d heads, %d sectors/track\n", + printf(_("%s: %d cylinders, %d heads, %d sectors/track\n"), dev, g.cylinders, g.heads, g.sectors); else - printf("%s: unknown geometry\n", dev); + printf(_("%s: unknown geometry\n"), dev); } /* for compatibility with earlier fdisk: provide option -s */ void do_size (char *dev, int silent) { - int fd, size; + int fd; + long size; fd = my_open(dev, 0, silent); if (fd < 0) @@ -2567,7 +2525,7 @@ do_size (char *dev, int silent) { if(ioctl(fd, BLKGETSIZE, &size)) { if(!silent) { perror(dev); - fatal("BLKGETSIZE ioctl failed for %s\n", dev); + fatal(_("BLKGETSIZE ioctl failed for %s\n"), dev); } return; } @@ -2579,9 +2537,9 @@ do_size (char *dev, int silent) { return; if (silent) - printf("%s: %9d\n", dev, size); + printf("%s: %9ld\n", dev, size); else - printf("%d\n", size); + printf("%ld\n", size); total_size += size; } @@ -2644,7 +2602,7 @@ do_activate (char **av, int ac, char *arg) { else printf("%s#%d\n", dev, pno); if (z->partitions[pno].p.bootable != 0x80) - warn("bad active byte: 0x%x instead of 0x80\n", + warn(_("bad active byte: 0x%x instead of 0x80\n"), z->partitions[pno].p.bootable); } } @@ -2661,7 +2619,7 @@ do_activate (char **av, int ac, char *arg) { /* then write to disk */ if(write_partitions(dev, fd, z)) - warn("Done\n\n"); + warn(_("Done\n\n")); else exit_status = 1; } @@ -2670,8 +2628,8 @@ do_activate (char **av, int ac, char *arg) { if (z->partitions[pno].p.bootable) i++; if (i != 1) - warn("You have %d active primary partitions. This does not matter for LILO,\n" - "but the DOS MBR will only boot a disk with 1 active partition.\n", i); + warn(_("You have %d active primary partitions. This does not matter for LILO,\n" + "but the DOS MBR will only boot a disk with 1 active partition.\n"), i); } void @@ -2684,7 +2642,7 @@ set_unhidden (struct disk_desc *z, char *pnam) { if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17) id -= 0x10; else - fatal("partition %s has id %x and is not hidden\n", pnam, id); + fatal(_("partition %s has id %x and is not hidden\n"), pnam, id); z->partitions[pno].p.sys_type = id; } @@ -2714,7 +2672,7 @@ do_unhide (char **av, int ac, char *arg) { /* then write to disk */ if(write_partitions(dev, fd, z)) - warn("Done\n\n"); + warn(_("Done\n\n")); else exit_status = 1; } @@ -2740,11 +2698,11 @@ void do_change_id(char *dev, char *pnam, char *id) { } i = strtoul(id, NULL, 16); if (i > 255) - fatal("Bad Id %x\n", i); + fatal(_("Bad Id %x\n"), i); z->partitions[pno].p.sys_type = i; if(write_partitions(dev, fd, z)) - warn("Done\n\n"); + warn(_("Done\n\n")); else exit_status = 1; } @@ -2755,7 +2713,7 @@ do_reread(char *dev) { fd = my_open(dev, 0, 0); if(reread_ioctl(fd)) - printf("This disk is currently in use.\n"); + printf(_("This disk is currently in use.\n")); } /* @@ -2772,26 +2730,26 @@ do_fdisk(char *dev){ if (stat(dev, &statbuf) < 0) { perror(dev); - fatal("Fatal error: cannot find %s\n", dev); + fatal(_("Fatal error: cannot find %s\n"), dev); } if (!S_ISBLK(statbuf.st_mode)) { - warn("Warning: %s is not a block device\n", dev); + warn(_("Warning: %s is not a block device\n"), dev); + no_reread = 1; } fd = my_open(dev, !no_write, 0); if(!no_write && !no_reread) { - warn("Checking that no-one is using this disk right now ...\n"); + warn(_("Checking that no-one is using this disk right now ...\n")); if(reread_ioctl(fd)) { - printf(" -This disk is currently in use - repartitioning is probably a bad idea. -Umount all file systems, and swapoff all swap partitions on this disk. -Use the --no-reread flag to suppress this check.\n"); + printf(_("\nThis disk is currently in use - repartitioning is probably a bad idea." + "Umount all file systems, and swapoff all swap partitions on this disk." + "Use the --no-reread flag to suppress this check.\n")); if (!force) { - printf("Use the --force flag to overrule all checks.\n"); + printf(_("Use the --force flag to overrule all checks.\n")); exit(1); } } else - warn("OK"); + warn(_("OK")); } z = &oldp; @@ -2800,11 +2758,11 @@ Use the --no-reread flag to suppress this check.\n"); get_cylindersize(dev, fd, 0); get_partitions(dev, fd, z); - printf("Old situation:\n"); + printf(_("Old situation:\n")); out_partitions(dev, z); if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0) - fatal("Partition %d does not exist, cannot change it\n", one_only); + fatal(_("Partition %d does not exist, cannot change it\n"), one_only); z = &newp; @@ -2812,35 +2770,35 @@ Use the --no-reread flag to suppress this check.\n"); read_input(dev, interactive, z); - printf("New situation:\n"); + printf(_("New situation:\n")); out_partitions(dev, z); if (!partitions_ok(z) && !force) { if(!interactive) - fatal("I don't like these partitions - nothing changed.\n" - "(If you really want this, use the --force option.)\n"); + fatal(_("I don't like these partitions - nothing changed.\n" + "(If you really want this, use the --force option.)\n")); else - printf("I don't like this - probably you should answer No\n"); + printf(_("I don't like this - probably you should answer No\n")); } ask: if (interactive) { if (no_write) - printf("Are you satisfied with this? [ynq] "); + printf(_("Are you satisfied with this? [ynq] ")); else - printf("Do you want to write this to disk? [ynq] "); + printf(_("Do you want to write this to disk? [ynq] ")); answer = c = getchar(); while (c != '\n' && c != EOF) c = getchar(); if (c == EOF) - printf("\nsfdisk: premature end of input\n"); + printf(_("\nsfdisk: premature end of input\n")); if (c == EOF || answer == 'q' || answer == 'Q') { - fatal("Quitting - nothing changed\n"); + fatal(_("Quitting - nothing changed\n")); } else if (answer == 'n' || answer == 'N') { continue; } else if (answer == 'y' || answer == 'Y') { break; } else { - printf("Please answer one of y,n,q\n"); + printf(_("Please answer one of y,n,q\n")); goto ask; } } else @@ -2848,15 +2806,15 @@ Use the --no-reread flag to suppress this check.\n"); } if(write_partitions(dev, fd, z)) - printf("Successfully wrote the new partition table\n\n"); + printf(_("Successfully wrote the new partition table\n\n")); else exit_status = 1; reread_disk_partition(dev, fd); - warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n" + warn(_("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n" "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n" - "(See fdisk(8).)\n"); + "(See fdisk(8).)\n")); sync(); /* superstition */ sleep(3); diff --git a/games/Makefile b/games/Makefile index 58a8f8f6..23297857 100644 --- a/games/Makefile +++ b/games/Makefile @@ -4,7 +4,7 @@ # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) # May be distributed under the GPL # - +include ../make_include include ../MCONFIG # Where to put man pages? diff --git a/games/banner.c b/games/banner.c index 400076e6..a429c842 100644 --- a/games/banner.c +++ b/games/banner.c @@ -29,9 +29,12 @@ * 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. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support */ -/* +/* * banner - prints large signs * banner [-w#] [-d] [-t] message ... */ @@ -41,6 +44,7 @@ #include #include #include +#include "nls.h" #define MAXMSG 1024 #define DWIDTH 132 @@ -1019,11 +1023,12 @@ main(argc, argv) char **argv; { int ch; - -#ifdef __linux__ extern char *__progname; __progname = argv[0]; -#endif + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); while ((ch = getopt(argc, argv, "w:td")) != EOF) switch(ch) { @@ -1040,7 +1045,7 @@ main(argc, argv) break; case '?': default: - fprintf(stderr, "usage: banner [-w width]\n"); + fprintf(stderr, _("usage: banner [-w width]\n")); exit(1); } argc -= optind; @@ -1060,7 +1065,7 @@ main(argc, argv) } nchars = strlen(message); } else { - fprintf(stderr,"Message: "); + fprintf(stderr,_("Message: ")); (void)fgets(message, sizeof(message), stdin); nchars = strlen(message); message[nchars--] = '\0'; /* get rid of newline */ @@ -1094,7 +1099,7 @@ main(argc, argv) for (i = 0; i < nchars; i++) if ((u_char) message[i] >= NCHARS || asc_ptr[(u_char) message[i]] == 0) { - warnx("The character '%c' is not in my character set", + warnx(_("The character '%c' is not in my character set"), message[i]); j++; } @@ -1102,7 +1107,7 @@ main(argc, argv) exit(1); if (trace) - printf("Message '%s' is OK\n",message); + printf(_("Message '%s' is OK\n"),message); /* Now have message. Print it one character at a time. */ for (i = 0; i < nchars; i++) { diff --git a/getopt-1.0.3a/COPYING b/getopt-1.0.3b/COPYING similarity index 100% rename from getopt-1.0.3a/COPYING rename to getopt-1.0.3b/COPYING diff --git a/getopt-1.0.3a/Changelog b/getopt-1.0.3b/Changelog similarity index 100% rename from getopt-1.0.3a/Changelog rename to getopt-1.0.3b/Changelog diff --git a/getopt-1.0.3a/Makefile b/getopt-1.0.3b/Makefile similarity index 97% rename from getopt-1.0.3a/Makefile rename to getopt-1.0.3b/Makefile index 0d4a5ad0..92e99e9d 100644 --- a/getopt-1.0.3a/Makefile +++ b/getopt-1.0.3b/Makefile @@ -1,5 +1,6 @@ .SUFFIXES: +include ../make_include include ../MCONFIG GETOPTDIR=$(USRLIBDIR)/getopt diff --git a/getopt-1.0.3a/README b/getopt-1.0.3b/README similarity index 100% rename from getopt-1.0.3a/README rename to getopt-1.0.3b/README diff --git a/getopt-1.0.3a/TODO b/getopt-1.0.3b/TODO similarity index 100% rename from getopt-1.0.3a/TODO rename to getopt-1.0.3b/TODO diff --git a/getopt-1.0.3a/getopt.1 b/getopt-1.0.3b/getopt.1 similarity index 100% rename from getopt-1.0.3a/getopt.1 rename to getopt-1.0.3b/getopt.1 diff --git a/getopt-1.0.3a/getopt.c b/getopt-1.0.3b/getopt.c similarity index 85% rename from getopt-1.0.3a/getopt.c rename to getopt-1.0.3b/getopt.c index de643f1a..345c1b97 100644 --- a/getopt-1.0.3a/getopt.c +++ b/getopt-1.0.3b/getopt.c @@ -28,6 +28,10 @@ * Version 1.0.2: Thu Jun 11 1998 (not present) * Fixed gcc-2.8.1 warnings * Fixed --version/-V option (not present) + * Version 1.0.3 + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -35,6 +39,7 @@ #include #include #include +#include "../lib/nls.h" #if LIBCGETOPT #include @@ -77,7 +82,7 @@ void *our_malloc(size_t size) { void *ret=malloc(size); if (! ret) { - fputs("getopt: Out of memory!",stderr); + fprintf(stderr,_("%s: Out of memory!\n"),"getopt"); exit(3); } return(ret); @@ -87,7 +92,7 @@ void *our_realloc(void *ptr, size_t size) { void *ret=realloc(ptr,size); if (! ret && size) { - fputs("getopt: Out of memory!",stderr); + fprintf(stderr,_("%s: Out of memory!\n"), "getopt"); exit(3); } return(ret); @@ -221,7 +226,7 @@ void parse_error(const char *message) { if (message) fprintf(stderr,"getopt: %s\n",message); - fputs("Try `getopt --help' for more information.\n",stderr); + fputs(_("Try `getopt --help' for more information.\n"),stderr); exit(2); } @@ -287,8 +292,8 @@ void add_long_options(char *options) arg_opt=required_argument; } if (strlen(tokptr) == 0) - parse_error("empty long option after " - "-l or --long argument"); + parse_error(_("empty long option after " + "-l or --long argument")); } add_longopt(tokptr,arg_opt); } @@ -307,25 +312,25 @@ void set_shell(const char *new_shell) else if (!strcmp(new_shell,"csh")) shell=TCSH; else - parse_error("unknown shell after -s or --shell argument"); + parse_error(_("unknown shell after -s or --shell argument")); } void print_help(void) { - fputs("Usage: getopt optstring parameters\n",stderr); - fputs(" getopt [options] [--] optstring parameters\n",stderr); - fputs(" getopt [options] -o|--options optstring [options] [--]\n",stderr); - fputs(" parameters\n",stderr); - fputs(" -a, --alternative Allow long options starting with single -\n",stderr); - fputs(" -h, --help This small usage guide\n",stderr); - fputs(" -l, --longoptions=longopts Long options to be recognized\n",stderr); - fputs(" -n, --name=progname The name under which errors are reported\n",stderr); - fputs(" -o, --options=optstring Short options to be recognized\n",stderr); - fputs(" -q, --quiet Disable error reporting by getopt(3)\n",stderr); - fputs(" -Q, --quiet-output No normal output\n",stderr); - fputs(" -s, --shell=shell Set shell quoting conventions\n",stderr); - fputs(" -T, --test Test for getopt(1) version\n",stderr); - fputs(" -V, --version Output version information\n",stderr); + fputs(_("Usage: getopt optstring parameters\n"),stderr); + fputs(_(" getopt [options] [--] optstring parameters\n"),stderr); + fputs(_(" getopt [options] -o|--options optstring [options] [--]\n"),stderr); + fputs(_(" parameters\n"),stderr); + fputs(_(" -a, --alternative Allow long options starting with single -\n"),stderr); + fputs(_(" -h, --help This small usage guide\n"),stderr); + fputs(_(" -l, --longoptions=longopts Long options to be recognized\n"),stderr); + fputs(_(" -n, --name=progname The name under which errors are reported\n"),stderr); + fputs(_(" -o, --options=optstring Short options to be recognized\n"),stderr); + fputs(_(" -q, --quiet Disable error reporting by getopt(3)\n"),stderr); + fputs(_(" -Q, --quiet-output No normal output\n"),stderr); + fputs(_(" -s, --shell=shell Set shell quoting conventions\n"),stderr); + fputs(_(" -T, --test Test for getopt(1) version\n"),stderr); + fputs(_(" -V, --version Output version information\n"),stderr); exit(2); } @@ -361,6 +366,10 @@ int main(int argc, char *argv[]) int opt; int compatible=0; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + init_longopt(); if (getenv("GETOPT_COMPATIBLE")) @@ -375,7 +384,7 @@ int main(int argc, char *argv[]) exit(0); } else - parse_error("missing optstring argument"); + parse_error(_("missing optstring argument")); } if (argv[1][0] != '-' || compatible) { @@ -421,19 +430,19 @@ int main(int argc, char *argv[]) case 'T': exit(4); case 'V': - printf("getopt (enhanced) 1.0.3\n"); + printf(_("getopt (enhanced) 1.0.3\n")); exit(0); case '?': case ':': parse_error(NULL); default: - parse_error("internal error, contact the author."); + parse_error(_("internal error, contact the author.")); } if (!optstr) { if (optind >= argc) - parse_error("missing optstring argument"); + parse_error(_("missing optstring argument")); else { optstr=our_malloc(strlen(argv[optind])+1); strcpy(optstr,argv[optind]); diff --git a/getopt-1.0.3a/gnu/getopt.c b/getopt-1.0.3b/gnu/getopt.c similarity index 100% rename from getopt-1.0.3a/gnu/getopt.c rename to getopt-1.0.3b/gnu/getopt.c diff --git a/getopt-1.0.3a/gnu/getopt.h b/getopt-1.0.3b/gnu/getopt.h similarity index 100% rename from getopt-1.0.3a/gnu/getopt.h rename to getopt-1.0.3b/gnu/getopt.h diff --git a/getopt-1.0.3a/gnu/getopt1.c b/getopt-1.0.3b/gnu/getopt1.c similarity index 100% rename from getopt-1.0.3a/gnu/getopt1.c rename to getopt-1.0.3b/gnu/getopt1.c diff --git a/getopt-1.0.3a/parse.bash b/getopt-1.0.3b/parse.bash similarity index 100% rename from getopt-1.0.3a/parse.bash rename to getopt-1.0.3b/parse.bash diff --git a/getopt-1.0.3a/parse.tcsh b/getopt-1.0.3b/parse.tcsh similarity index 100% rename from getopt-1.0.3a/parse.tcsh rename to getopt-1.0.3b/parse.tcsh diff --git a/getopt-1.0.3a/test.bash b/getopt-1.0.3b/test.bash similarity index 100% rename from getopt-1.0.3a/test.bash rename to getopt-1.0.3b/test.bash diff --git a/getopt-1.0.3a/test.tcsh b/getopt-1.0.3b/test.tcsh similarity index 100% rename from getopt-1.0.3a/test.tcsh rename to getopt-1.0.3b/test.tcsh diff --git a/getpoe.sh b/getpoe.sh deleted file mode 100644 index 6c808946..00000000 --- a/getpoe.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -x -adm=/tmp/admutil -poe=/tmp/poeigl -tmp=/tmp/$$ -diffs=poe.diffs - -if [ -e $diffs ]; then rm $diffs; fi -if [ ! -d $tmp ]; then mkdir $tmp; fi - -function cmpandcp () { - dir=$1; - i=$2; - name=${i#$poe/}; - name=${name#$adm/}; - target=$dir/$name; - diff -u $target.c $i.c >> $diffs; - mv $target.c $tmp/$name.c; - mv $i.c $target.c; - for k in man 1 8; do - if [ -e $i.$k ]; then - for j in 1 8; do - if [ -e $target.$j ]; then - diff -u $target.$j $i.$k >> $diffs; - mv $target.$j $tmp/$name.$j; - mv $i.$k $target.$j; - fi - done - fi - done -} - - -# login-utils -for i in $poe/agetty $adm/last $poe/login $adm/newgrp $adm/passwd \ - $adm/shutdown $poe/simpleinit; do - cmpandcp login-utils $i; -done - -# misc-utils -cmpandcp misc-utils $poe/hostid; -cmpandcp misc-utils $poe/domainname; - -# sys-utils -cmpandcp sys-utils $adm/ctrlaltdel; - -# READMEs -diff -u $adm/README login-utils/README.admutil >> $diffs -mv $adm/README login-utils/README.admutil - -diff -u $poe/README login-utils/README.poeigl >> $diffs -mv $poe/README login-utils/README.poeigl - -diff -u $poe/README.getty login-utils >> $diffs -mv $poe/README.getty login-utils - -exit diff --git a/kbd/Makefile b/kbd/Makefile new file mode 100644 index 00000000..30bfb0e8 --- /dev/null +++ b/kbd/Makefile @@ -0,0 +1,25 @@ +# Makefile -- Makefile for util-linux Linux utilities +# +include ../make_include +include ../MCONFIG + +# Where to put man pages? + +MAN8= kbdrate.8 + +# Where to put binaries? +# See the "install" rule for the links. . . + +SBIN= kbdrate + +all: $(SBIN) + +kbdrate: kbdrate.o + +install: all + $(INSTALLDIR) $(SBINDIR) $(MAN8DIR) + $(INSTALLBIN) $(SBIN) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +clean: + -rm -f *.o *~ core $(SBIN) diff --git a/kbd/README b/kbd/README new file mode 100644 index 00000000..97ca5bde --- /dev/null +++ b/kbd/README @@ -0,0 +1,2 @@ +This stuff belongs in the kbd package and will disappear here. +It is left for a while - version in kbd* and here will be identical. diff --git a/kbd/README.clear b/kbd/README.clear new file mode 100644 index 00000000..7684132d --- /dev/null +++ b/kbd/README.clear @@ -0,0 +1,7 @@ +RedHat and SuSE take the program clear from ncurses. + A 20KB program equivalent to "tput clear". + +Slackware uses the script. + +So, both versions will behave identically, and +Slackware saves 20 KB. diff --git a/kbd/README.reset b/kbd/README.reset new file mode 100644 index 00000000..8060d265 --- /dev/null +++ b/kbd/README.reset @@ -0,0 +1,20 @@ +RedHat and SuSE take the program reset from ncurses, + where reset is a name for the program tset. + It is approximately equivalent to + stty sane; tputs rs1; tputs rs2; tputs rf + with `tputs rf' replaced by `tputs if' when there is an + init_file but no reset_file. In the comments it wonders + whether also sending rs3, rmacs, rmul, rmm might be a good idea. + +Slackware uses the small script given here. + The part `echo -e \\033c' is the canonical reset of the kernel + console status, and is equivalent to `tputs rs1' for a linux + terminal. + +So, both versions are approximately the same. + + +[A disadvantage of `echo -e \\033c' might be that it is potentially +wrong on a non-vt100, non-xterm, non-linux terminal. +An advantage is that there are terminfo entries for xterm around +that only use rs1=^O as reset, and then \Ec is much better.] diff --git a/kbd/clear b/kbd/clear new file mode 100755 index 00000000..73d1ebe1 --- /dev/null +++ b/kbd/clear @@ -0,0 +1,2 @@ +#! /bin/sh +tput clear diff --git a/kbd/clear.1 b/kbd/clear.1 new file mode 100644 index 00000000..9d208230 --- /dev/null +++ b/kbd/clear.1 @@ -0,0 +1,31 @@ +.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu) +.\" May be distributed under the GNU General Public License +.TH CLEAR 1 "10 October 1993" "Linux 0.99" "Linux Programmer's Manual" +.SH NAME +clear \- clear terminal screen +.SH SYNOPSIS +.BR clear +.SH DESCRIPTION +.B clear +calls +.BR tput (1) +with the +.I clear +argument. This causes +.B tput +to attempt to clear the screen checking the data in +.I /etc/termcap +(for the GNU or BSD +.BR tput ) +or in the terminfo database +(for the +.B ncurses +.BR tput ) +and sending the appropriate sequence to the terminal. This command can be +redirected to clear the screen of some other terminal. +.SH "SEE ALSO" +.BR reset (1), +.BR stty (1), +.BR tput (1) +.SH AUTHOR +Rik Faith (faith@cs.unc.edu) diff --git a/kbd/kbdrate.8 b/kbd/kbdrate.8 new file mode 100644 index 00000000..66715de0 --- /dev/null +++ b/kbd/kbdrate.8 @@ -0,0 +1,68 @@ +.\" Copyright 1992, 1994 Rickard E. Faith (faith@cs.unc.edu) +.\" May be distributed under the GNU General Public License +.\" Updated Wed Jun 22 21:09:43 1994, faith@cs.unc.edu +.\" +.TH KBDRATE 8 "22 June 1994" "Linux 1.1.19" "Linux Programmer's Manual" +.SH NAME +kbdrate \- reset the keyboard repeat rate and delay time +.SH SYNOPSIS +.B "kbdrate [ \-s ] [ \-r" +rate +.B "] [ \-d" +delay +.B ] +.SH DESCRIPTION +.B kbdrate +is used to change the keyboard repeat rate and delay time. The delay +is the amount of time that a key must be depressed before it will start to +repeat. + +Using +.B kbdrate +without any options will reset the repeat rate to 10.9 characters per second (cps) +and the delay to 250 milliseconds (ms) for Intel- and M68K-based systems. +These are the IBM defaults. On SPARC-based systems it will reset the repeat rate +to 5 cps and the delay to 200 ms. + +.SH OPTIONS +.TP +.B \-s +Silent. No messages are printed. +.TP +.BI \-r " rate" +Change the keyboard repeat rate to +.I rate +cps. For Intel-based systems, the allowable range is from 2.0 to 30.0 cps. +Only certain, specific values are possible, and the program will select the +nearest possible value to the one specified. The possible values are given, +in characters per second, as follows: 2.0, 2.1, 2.3, 2.5, 2.7, 3.0, 3.3, 3.7, +4.0, 4.3, 4.6, 5.0, 5.5, 6.0, 6.7, 7.5, 8.0, 8.6, 9.2, 10.0, 10.9, 12.0, 13.3, +15.0, 16.0, 17.1, 18.5, 20.0, 21.8, 24.0, 26.7, 30.0. +For SPARC-based systems, the allowable range is from 0 (no repeat) to 50 cps. +.TP +.BI \-d " delay" +Change the delay to +.I delay +milliseconds. +For Intel-based systems, the allowable range is from 250 to 1000 ms, +in 250 ms steps. For SPARC systems, possible values are between 10 ms and 1440 ms, +in 10 ms steps. +.SH BUGS +Not all keyboards support all rates. +.PP +Not all keyboards have the rates mapped in the same way. +.PP +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 util-linux@math.uio.no. +.PP +All this is very architecture dependent. +Nowadays +.B kbdrate +first tries the KDKBDREP and KIOCSRATE ioctls. +(The former usually works on an m68k machine, the latter for SPARC.) +When these ioctls fail an ioport interface as on i386 is assumed. +.SH FILES +.I /etc/rc.local +.br +.I /dev/port diff --git a/sys-utils/kbdrate.c b/kbd/kbdrate.c similarity index 58% rename from sys-utils/kbdrate.c rename to kbd/kbdrate.c index 50442945..5388a6ef 100644 --- a/sys-utils/kbdrate.c +++ b/kbd/kbdrate.c @@ -15,10 +15,10 @@ will start to repeat. Usage examples: -kbdrate set rate to IBM default (10.9 cps, 250mS delay) -kbdrate -r 30.0 set rate to 30 cps and delay to 250mS -kbdrate -r 20.0 -s set rate to 20 cps (delay 250mS) -- don't print message -kbdrate -r 0 -d 0 set rate to 2.0 cps and delay to 250 mS +kbdrate set rate to IBM default (10.9 cps, 250ms delay) +kbdrate -r 30.0 set rate to 30 cps and delay to 250ms +kbdrate -r 20.0 -s set rate to 20 cps (delay 250ms) -- don't print message +kbdrate -r 0 -d 0 set rate to 2.0 cps and delay to 250 ms I find it useful to put kbdrate in my /etc/rc file so that the keyboard rate is set to something that I find comfortable at boot time. This sure @@ -57,6 +57,15 @@ beats rebuilding the kernel! kbdrate now first tries if the KDKBDREP ioctl is available. If it is, it is used, else the old method is applied. + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + + 1999-03-17 + Linux/SPARC modifications by Jeffrey Connell : + It seems that the KDKBDREP ioctl is not available on this platform. + However, Linux/SPARC has its own ioctl for this, with yet another + different measurement system. Thus, try for KIOCSRATE, too. + */ #include @@ -65,14 +74,18 @@ beats rebuilding the kernel! #include #include #include -#include -#if LINUX_VERSION_CODE >= 131072 -/* kd.h is not available with all linux versions. 131072 is equivalent - to linux 2.0.0 */ + +#include "../defines.h" +#ifdef HAVE_kd_h #include #endif +#ifdef __sparc__ +#include +#include +#endif -#define VERSION "1.3" +#include "nls.h" +#include "../version.h" static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, 133, 120, 109, 100, 92, 86, 80, 75, 67, @@ -83,15 +96,98 @@ static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, static int valid_delays[] = { 250, 500, 750, 1000 }; #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int )) +int +KDKBDREP_ioctl_ok(double rate, int delay, int silent) { #ifdef KDKBDREP -static int ioctl_possible = 0; -struct kbd_repeat kbdrep_s; -#endif + /* This ioctl is defined in but is not + implemented anywhere - must be in some m68k patches. */ + struct kbd_repeat kbdrep_s; + + /* don't change, just test */ + kbdrep_s.rate = -1; + kbdrep_s.delay = -1; + if (ioctl( 0, KDKBDREP, &kbdrep_s )) { + if (errno == EINVAL) + return 0; + perror( "ioctl(KDKBDREP)" ); + exit( 1 ); + } + + /* do the change */ + 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 (ioctl( 0, KDKBDREP, &kbdrep_s )) { + perror( "ioctl(KDKBDREP)" ); + exit( 1 ); + } + + /* report */ + if (kbdrep_s.rate == 0) + rate = 0; + else + rate = 1000.0 / (double) kbdrep_s.rate; + + if (!silent) + printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"), + rate, kbdrep_s.delay ); + + return 1; /* success! */ + +#else /* no KDKBDREP */ + return 0; +#endif /* KDKBDREP */ +} + +int +KIOCSRATE_ioctl_ok(double rate, int delay, int silent) { +#ifdef KIOCSRATE + struct kbd_rate kbdrate_s; + int fd; + + fd = open("/dev/kbd", O_RDONLY); + if (fd == -1) { + perror( "open(/dev/kbd)" ); + exit( 1 ); + } + + kbdrate_s.rate = (int) (rate + 0.5); /* must be integer, so round up */ + kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */ + if (kbdrate_s.rate > 50) + kbdrate_s.rate = 50; + + if (ioctl( fd, KIOCSRATE, &kbdrate_s )) { + perror( "ioctl(KIOCSRATE)" ); + exit( 1 ); + } + close( fd ); + + if (!silent) + printf( "Typematic Rate set to %d cps (delay = %d ms)\n", + kbdrate_s.rate, kbdrate_s.delay * 1000 / HZ ); + + return 1; +#else /* no KIOCSRATE */ + return 0; +#endif /* KIOCSRATE */ +} int main( int argc, char **argv ) { +#ifdef __sparc__ + double rate = 5.0; /* Default rate */ + int delay = 200; /* Default delay */ +#else double rate = 10.9; /* Default rate */ int delay = 250; /* Default delay */ +#endif int value = 0x7f; /* Maximum delay with slowest rate */ /* DO NOT CHANGE this value */ int silent = 0; @@ -101,7 +197,12 @@ int main( int argc, char **argv ) int i; extern char *optarg; - while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + + while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) { switch (c) { case 'r': rate = atof( optarg ); @@ -113,43 +214,17 @@ int main( int argc, char **argv ) silent = 1; break; case 'v': - fprintf( stderr, "util-linux kbdrate " VERSION "\n"); + fprintf( stderr, "util-linux %s kbdrate\n", UTIL_LINUX_VERSION); exit(0); } + } + + if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */ + return 0; + + if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */ + return 0; -#ifdef KDKBDREP - kbdrep_s.rate = -1; /* don't change, just test */ - kbdrep_s.delay = -1; - if (ioctl( 0, KDKBDREP, &kbdrep_s )) { - if (errno == EINVAL) - ioctl_possible = 0; - else { - perror( "ioctl(KDKBDREP)" ); - exit( 1 ); - } - } else ioctl_possible = 1; - - if (ioctl_possible) { - 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 (ioctl( 0, KDKBDREP, &kbdrep_s )) { - perror( "ioctl(KDKBDREP)" ); - exit( 1 ); - } - - if (!silent) - printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n", - 1000.0 / (double)kbdrep_s.rate, kbdrep_s.delay ); - } else { -#endif /* The ioport way */ @@ -169,7 +244,7 @@ int main( int argc, char **argv ) } if ( (fd = open( "/dev/port", O_RDWR )) < 0) { - perror( "Cannot open /dev/port" ); + perror( _("Cannot open /dev/port") ); exit( 1 ); } @@ -193,13 +268,9 @@ int main( int argc, char **argv ) close( fd ); - if (!silent) printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n", + if (!silent) printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"), valid_rates[value & 0x1f] / 10.0, valid_delays[ (value & 0x60) >> 5 ] ); -#ifdef KDKBDREP - } -#endif - return 0; } diff --git a/kbd/reset b/kbd/reset new file mode 100755 index 00000000..fb9834db --- /dev/null +++ b/kbd/reset @@ -0,0 +1,11 @@ +#!/bin/sh +stty sane +tput clear +tput rmacs +tput rmm +tput rmso +tput rmul +tput rs1 +tput rs2 +tput rs3 +echo -e \\033c diff --git a/lib/Makefile b/lib/Makefile index 5503a605..a9f8596d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,13 +1,16 @@ +include ../make_include include ../MCONFIG CFLAGS=-I$(LIB) $(OPT) -all: err.o my_reboot.o setproctitle.o +all: err.o my_reboot.o setproctitle.o env.o err.o: err.c my_reboot.o: my_reboot.c linux_reboot.h +env.o: env.h + setproctitle.o: setproctitle.h .PHONY: clean diff --git a/lib/env.c b/lib/env.c new file mode 100644 index 00000000..69c821c2 --- /dev/null +++ b/lib/env.c @@ -0,0 +1,73 @@ +/* + * Security checks of enviroment + * Added from shadow-utils package + * by Arkadiusz Mi¶kiewicz + * + */ + +#include +#include +#include +#include "env.h" + +extern char **environ; + +static char * const forbid[] = { + "_RLD_=", + "BASH_ENV=", /* GNU creeping featurism strikes again... */ + "ENV=", + "HOME=", + "IFS=", + "KRB_CONF=", + "LD_", /* anything with the LD_ prefix */ + "LIBPATH=", + "MAIL=", + "NLSPATH=", + "PATH=", + "SHELL=", + "SHLIB_PATH=", + (char *) 0 +}; + +/* these are allowed, but with no slashes inside + (to work around security problems in GNU gettext) */ +static char * const noslash[] = { + "LANG=", + "LANGUAGE=", + "LC_", /* anything with the LC_ prefix */ + (char *) 0 +}; + +void +sanitize_env(void) +{ + char **envp = environ; + char * const *bad; + char **cur; + char **move; + + for (cur = envp; *cur; cur++) { + for (bad = forbid; *bad; bad++) { + if (strncmp(*cur, *bad, strlen(*bad)) == 0) { + for (move = cur; *move; move++) + *move = *(move + 1); + cur--; + break; + } + } + } + + for (cur = envp; *cur; cur++) { + for (bad = noslash; *bad; bad++) { + if (strncmp(*cur, *bad, strlen(*bad)) != 0) + continue; + if (!strchr(*cur, '/')) + continue; /* OK */ + for (move = cur; *move; move++) + *move = *(move + 1); + cur--; + break; + } + } +} + diff --git a/lib/env.h b/lib/env.h new file mode 100644 index 00000000..d69b4f29 --- /dev/null +++ b/lib/env.h @@ -0,0 +1,2 @@ +extern void sanitize_env (void); + diff --git a/lib/err.c b/lib/err.c index 2731a714..d5319224 100644 --- a/lib/err.c +++ b/lib/err.c @@ -43,9 +43,11 @@ #include #endif +#include "../defines.h" +#ifdef HAVE_progname extern char *__progname; /* Program name, from crt0. */ -#ifdef __linux__ -char *__progname; +#else +char *__progname = "foo"; /* probably libc4 */ #endif __dead void diff --git a/lib/nls.h b/lib/nls.h new file mode 100644 index 00000000..67b42a99 --- /dev/null +++ b/lib/nls.h @@ -0,0 +1,33 @@ + +#include "../defines.h" /* for HAVE_locale_h */ + +#ifndef PACKAGE +#define PACKAGE "util-linux" +#endif + +#ifndef LOCALEDIR +#define LOCALEDIR "/usr/share/locale" +#endif + +#ifdef HAVE_locale_h +# include +#endif + +#ifdef ENABLE_NLS +# include +# define _(Text) gettext (Text) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# undef bindtextdomain +# define bindtextdomain(Domain, Directory) /* empty */ +# undef textdomain +# define textdomain(Domain) /* empty */ +# define _(Text) (Text) +# define N_(Text) (Text) +#endif + + diff --git a/lib/setproctitle.c b/lib/setproctitle.c index bff1362d..319bc6a9 100644 --- a/lib/setproctitle.c +++ b/lib/setproctitle.c @@ -20,10 +20,6 @@ #include #include "setproctitle.h" -#ifndef SPT_PADCHAR -#define SPT_PADCHAR ' ' -#endif - #ifndef SPT_BUFSIZE #define SPT_BUFSIZE 2048 #endif @@ -65,7 +61,6 @@ initproctitle (int argc, char **argv) { /* 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; @@ -82,16 +77,14 @@ setproctitle (const char *fmt,...) { i = argv_lth - 2; buf[i] = '\0'; } + memset(argv0[0], '\0', argv_lth); /* clear the memory area */ (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]; @@ -108,10 +101,9 @@ setproctitle (const char *prog, const char *txt) { i = argv_lth - 2; buf[i] = '\0'; } + memset(argv0[0], '\0', argv_lth); /* clear the memory area */ (void) strcpy (argv0[0], buf); - p = &argv0[0][i]; - while (i < argv_lth) - *p++ = SPT_PADCHAR, i++; + argv0[1] = NULL; } #endif diff --git a/COPYING.GPL b/licenses/COPYING.GPL similarity index 100% rename from COPYING.GPL rename to licenses/COPYING.GPL diff --git a/COPYING.UCB b/licenses/COPYING.UCB similarity index 100% rename from COPYING.UCB rename to licenses/COPYING.UCB diff --git a/login-utils/Makefile b/login-utils/Makefile index f4bbc5a9..4dcfee26 100644 --- a/login-utils/Makefile +++ b/login-utils/Makefile @@ -3,9 +3,10 @@ # Revised: Sun Nov 10 20:28:43 1996 by faith@cs.unc.edu # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) # -# Suggested changed from Bauke Jan Douma have been +# Suggested changes from Bauke Jan Douma have been # implemented to handle shadow and sysvinit systems +include ../make_include include ../MCONFIG # Where to put man pages? @@ -37,7 +38,7 @@ USRBIN.PASSWD= passwd USRSBIN.PUTILS= vipw -ifeq "$(HAVE_LIBCRYPT)" "yes" +ifeq "$(NEED_LIBCRYPT)" "yes" CRYPT=-lcrypt endif @@ -84,9 +85,9 @@ all-misc: $(USRBIN.MISC) agetty.o: $(LIB)/pathnames.h agetty: agetty.o -chfn: chfn.o islocal.o setpwnam.o +chfn: chfn.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) -chsh: chsh.o islocal.o setpwnam.o +chsh: chsh.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) islocal.o: $(LIB)/pathnames.h last.o: $(LIB)/pathnames.h @@ -101,13 +102,17 @@ login: login.o $(LIB)/setproctitle.o checktty.o endif mesg: mesg.o $(ERR_O) + newgrp: newgrp.o $(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 + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) + vipw.o: $(LIB)/pathnames.h vipw: vipw.o @@ -127,7 +132,7 @@ login.o: $(LIB)/pathnames.h mesg.o: $(LIB)/err.h endif -passwd: passwd.o islocal.o setpwnam.o +passwd: passwd.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) ifeq "$(REQUIRE_PASSWORD)" "yes" diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 96d7b38d..c85526dc 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -4,6 +4,13 @@ be here. Now read the real man-page agetty.8 instead. -f option added by Eric Rasmussen - 12/28/95 + + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + + 1999-05-05 Thorsten Kranzkowski + - enable hardware flow control before displaying /etc/issue + */ #include @@ -23,6 +30,7 @@ #include #include #include +#include "nls.h" #ifdef __linux__ #include "pathnames.h" @@ -255,6 +263,10 @@ main(argc, argv) 0, /* no baud rates known yet */ }; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + /* The BSD-style init command passes us a useless process name. */ #ifdef SYSV_STYLE @@ -288,7 +300,7 @@ main(argc, argv) update_utmp(options.tty); #endif - debug("calling open_tty\n"); + debug(_("calling open_tty\n")); /* Open the tty as standard { input, output, error }. */ open_tty(options.tty, &termio, options.flags & F_LOCAL); @@ -301,12 +313,12 @@ main(argc, argv) } #endif /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */ - debug("calling termio_init\n"); - termio_init(&termio, options.speeds[FIRST_SPEED], options.flags & F_LOCAL); + debug(_("calling termio_init\n")); + termio_init(&termio, options.speeds[FIRST_SPEED], &options); /* write the modem init string and DON'T flush the buffers */ if (options.flags & F_INITSTRING) { - debug("writing init string\n"); + debug(_("writing init string\n")); write(1, options.initstring, strlen(options.initstring)); } @@ -316,7 +328,7 @@ main(argc, argv) } /* Optionally detect the baud rate from the modem status message. */ - debug("before autobaud\n"); + debug(_("before autobaud\n")); if (options.flags & F_PARSE) auto_baud(&termio); @@ -328,11 +340,11 @@ main(argc, argv) if (options.flags & F_WAITCRLF) { char ch; - debug("waiting for cr-lf\n"); + debug(_("waiting for cr-lf\n")); while(read(0, &ch, 1) == 1) { ch &= 0x7f; /* strip "parity bit" */ #ifdef DEBUGGING - fprintf(dbf, "read %c\n", ch); + fprintf(dbf, _("read %c\n"), ch); #endif if (ch == '\n' || ch == '\r') break; } @@ -341,7 +353,7 @@ main(argc, argv) chardata = init_chardata; if (!(options.flags & F_NOPROMPT)) { /* Read the login name. */ - debug("reading login name\n"); + debug(_("reading login name\n")); while ((logname = get_logname(&options, &chardata, &termio)) == 0) next_speed(&termio, &options); } @@ -362,7 +374,7 @@ main(argc, argv) /* Let the login program take care of password validation. */ (void) execl(options.login, options.login, "--", logname, (char *) 0); - error("%s: can't exec %s: %m", options.tty, options.login); + error(_("%s: can't exec %s: %m"), options.tty, options.login); exit(0); /* quiet GCC */ } @@ -382,7 +394,7 @@ parse_args(argc, argv, op) switch (c) { case 'I': if (!(op->initstring = malloc(strlen(optarg)))) { - error("can't malloc initstring"); + error(_("can't malloc initstring")); break; } { @@ -444,7 +456,7 @@ parse_args(argc, argv, op) break; case 't': /* time out */ if ((op->timeout = atoi(optarg)) <= 0) - error("bad timeout value: %s", optarg); + error(_("bad timeout value: %s"), optarg); break; case 'w': op->flags |= F_WAITCRLF; @@ -453,7 +465,7 @@ parse_args(argc, argv, op) usage(); } } - debug("after getopt loop\n"); + debug(_("after getopt loop\n")); if (argc < optind + 2) /* check parameter count */ usage(); @@ -471,7 +483,7 @@ parse_args(argc, argv, op) if (argc > optind && argv[optind]) setenv ("TERM", argv[optind], 1); - debug("exiting parseargs\n"); + debug(_("exiting parseargs\n")); } /* parse_speeds - parse alternate baud rates */ @@ -484,14 +496,14 @@ parse_speeds(op, arg) char *strtok(); char *cp; - debug("entered parse_speeds\n"); + debug(_("entered parse_speeds\n")); for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) - error("bad speed: %s", cp); + error(_("bad speed: %s"), cp); if (op->numspeed > MAX_SPEED) - error("too many alternate speeds"); + error(_("too many alternate speeds")); } - debug("exiting parsespeeds\n"); + debug(_("exiting parsespeeds\n")); } #ifdef SYSV_STYLE @@ -503,7 +515,6 @@ update_utmp(line) { struct utmp ut; time_t t; - int ut_fd; int mypid = getpid(); long time(); long lseek(); @@ -548,6 +559,7 @@ update_utmp(line) #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) updwtmp(_PATH_WTMP, &ut); #else + int ut_fd; int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { @@ -562,24 +574,26 @@ update_utmp(line) #endif } #else /* not __linux__ */ - if ((ut_fd = open(UTMP_FILE, 2)) < 0) { - error("%s: open for update: %m", UTMP_FILE); - } else { - long ut_size = sizeof(ut); /* avoid nonsense */ - - while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) { - if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) { - ut.ut_type = LOGIN_PROCESS; - ut.ut_time = time((long *) 0); - (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name)); - (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - (void) lseek(ut_fd, -ut_size, 1); - (void) write(ut_fd, (char *) &ut, sizeof(ut)); - (void) close(ut_fd); - return; - } - } - error("%s: no utmp entry", line); + { int ut_fd; + if ((ut_fd = open(UTMP_FILE, 2)) < 0) { + error(_("%s: open for update: %m"), UTMP_FILE); + } else { + long ut_size = sizeof(ut); /* avoid nonsense */ + + while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) { + if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) { + ut.ut_type = LOGIN_PROCESS; + ut.ut_time = time((long *) 0); + (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name)); + (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void) lseek(ut_fd, -ut_size, 1); + (void) write(ut_fd, (char *) &ut, sizeof(ut)); + (void) close(ut_fd); + return; + } + } + error(_("%s: no utmp entry"), line); + } } #endif /* __linux__ */ } @@ -607,20 +621,20 @@ open_tty(tty, tp, local) /* Sanity checks... */ if (chdir("/dev")) - error("/dev: chdir() failed: %m"); + error(_("/dev: chdir() failed: %m")); if (stat(tty, &st) < 0) error("/dev/%s: %m", tty); if ((st.st_mode & S_IFMT) != S_IFCHR) - error("/dev/%s: not a character device", tty); + error(_("/dev/%s: not a character device"), tty); /* Open the tty as standard input. */ (void) close(0); errno = 0; /* ignore close(2) errors */ - debug("open(2)\n"); + debug(_("open(2)\n")); if (open(tty, O_RDWR|O_NONBLOCK, 0) != 0) - error("/dev/%s: cannot open as standard input: %m", tty); + error(_("/dev/%s: cannot open as standard input: %m"), tty); } else { @@ -630,13 +644,13 @@ open_tty(tty, tp, local) */ if ((fcntl(0, F_GETFL, 0) & O_RDWR) != O_RDWR) - error("%s: not open for read/write", tty); + error(_("%s: not open for read/write"), tty); } /* Set up standard output and standard error file descriptors. */ - debug("duping\n"); + debug(_("duping\n")); if (dup(0) != 1 || dup(0) != 2) /* set up stdout and stderr */ - error("%s: dup problem: %m", tty); /* we have a problem */ + error(_("%s: dup problem: %m"), tty); /* we have a problem */ /* * The following ioctl will fail if stdin is not a tty, but also when @@ -668,10 +682,10 @@ char gbuf[1024]; char area[1024]; void -termio_init(tp, speed, local) +termio_init(tp, speed, op) struct termio *tp; int speed; - int local; + struct options *op; { /* @@ -686,19 +700,27 @@ termio_init(tp, speed, local) #endif tp->c_cflag = CS8 | HUPCL | CREAD | speed; - if (local) { + if (op->flags & F_LOCAL) { tp->c_cflag |= CLOCAL; } tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0; tp->c_cc[VMIN] = 1; tp->c_cc[VTIME] = 0; + + /* Optionally enable hardware flow control */ + +#ifdef CRTSCTS + if (op->flags & F_RTSCTS) + tp->c_cflag |= CRTSCTS; +#endif + (void) ioctl(0, TCSETA, tp); /* go to blocking input even in local mode */ fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK); - debug("term_io 2\n"); + debug(_("term_io 2\n")); } /* auto_baud - extract baud rate from modem status message */ @@ -878,9 +900,9 @@ do_prompt(op, tp) if (ut->ut_type == USER_PROCESS) users++; endutent(); - printf ("%d", users); + printf ("%d ", users); if (c == 'U') - printf (" user%s", users == 1 ? "" : "s"); + printf ((users == 1) ? _("user") : _("users")); break; } default: @@ -968,7 +990,7 @@ char *get_logname(op, cp, tp) if (read(0, &c, 1) < 1) { if (errno == EINTR || errno == EIO) exit(0); - error("%s: read: %m", op->tty); + error(_("%s: read: %m"), op->tty); } /* Do BREAK handling elsewhere. */ @@ -1014,7 +1036,7 @@ char *get_logname(op, cp, tp) if (!isascii(ascval) || !isprint(ascval)) { /* ignore garbage characters */ ; } else if (bp - logname >= sizeof(logname) - 1) { - error("%s: input overrun", op->tty); + error(_("%s: input overrun"), op->tty); } else { (void) write(1, &c, 1); /* echo the character */ *bp++ = ascval; /* and store it */ @@ -1138,10 +1160,7 @@ bcode(s) void usage() { - static char msg[] = - "[-hiLmw] [-l login_program] [-t timeout] [-I initstring] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] line baud_rate,... [termtype]"; - - fprintf(stderr, "Usage: %s %s\n", progname, msg); + fprintf(stderr, _("Usage: %s [-hiLmw] [-l login_program] [-t timeout] [-I initstring] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] line baud_rate,... [termtype]\n"), progname); exit(1); } @@ -1220,6 +1239,6 @@ error(va_alist) (void) close(fd); } #endif - (void) sleep((unsigned) 10); /* be kind to init(8) */ + (void) sleep((unsigned) 10); /* be kind to init(8) */ exit(1); } diff --git a/login-utils/checktty.c b/login-utils/checktty.c index 15873aa4..66fee733 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -1,6 +1,10 @@ /* checktty.c - linked into login, checks user against /etc/usertty Created 25-Aug-95 by Peter Orbaek Fixed by JDS June 1996 to clear lists and close files + + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + */ #include @@ -17,6 +21,7 @@ #include #include #include +#include "nls.h" #ifdef __linux__ # include @@ -38,13 +43,13 @@ char *hostname; void badlogin(const char *s) { - printf("badlogin: %s\n", s); + printf(_("badlogin: %s\n"), s); } void sleepexit(int x) { - printf("sleepexit %d\n", x); + printf(_("sleepexit %d\n"), x); exit(1); } #endif @@ -100,8 +105,8 @@ new_class(char *class) tc = (struct ttyclass *)malloc(sizeof(struct ttyclass)); if (tc == NULL) { - printf("login: memory low, login may fail\n"); - syslog(LOG_WARNING, "can't malloc for ttyclass"); + printf(_("login: memory low, login may fail\n")); + syslog(LOG_WARNING, _("can't malloc for ttyclass")); return NULL; } @@ -122,8 +127,8 @@ add_to_class(struct ttyclass *tc, char *tty) ge = (struct grplist *)malloc(sizeof(struct grplist)); if (ge == NULL) { - printf("login: memory low, login may fail\n"); - syslog(LOG_WARNING, "can't malloc for grplist"); + printf(_("login: memory low, login may fail\n")); + syslog(LOG_WARNING, _("can't malloc for grplist")); return; } @@ -135,8 +140,6 @@ 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) { @@ -150,16 +153,25 @@ isapty(const char *tty) #if defined(__linux__) if((stat(devname, &stb) >= 0) && S_ISCHR(stb.st_mode)) { + int majordev = major(stb.st_rdev); + + /* this is for linux versions before 1.3: use major 4 */ + if(majordev == TTY_MAJOR && minor(stb.st_rdev) >= 192) + return 1; #if defined(PTY_SLAVE_MAJOR) - /* this is for linux 1.3 and newer */ - if(major(stb.st_rdev) == PTY_SLAVE_MAJOR) + /* this is for linux 1.3 and newer: use major 3 */ + if(majordev == PTY_SLAVE_MAJOR) return 1; #endif - /* this is for linux versions before 1.3, backward compat. */ - if(major(stb.st_rdev) == TTY_MAJOR && minor(stb.st_rdev) >= 192) +#if defined(UNIX98_PTY_SLAVE_MAJOR) && defined(UNIX98_PTY_MAJOR_COUNT) + /* this is for linux 2.1.116 and newer: use majors 136-143 */ + if(majordev >= UNIX98_PTY_SLAVE_MAJOR && + majordev < UNIX98_PTY_SLAVE_MAJOR + UNIX98_PTY_MAJOR_COUNT) return 1; +#endif + } #endif return 0; @@ -416,7 +428,7 @@ checktty(const char *user, const char *tty, struct passwd *pwd) } /* there was a default rule, but user didn't match, reject! */ - printf("Login on %s from %s denied by default.\n", tty, hostname); + printf(_("Login on %s from %s denied by default.\n"), tty, hostname); badlogin(user); sleepexit(1); } @@ -427,7 +439,7 @@ checktty(const char *user, const char *tty, struct passwd *pwd) name of the tty where the user is trying to log in. So deny access! */ - printf("Login on %s from %s denied.\n", tty, hostname); + printf(_("Login on %s from %s denied.\n"), tty, hostname); badlogin(user); sleepexit(1); } diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 3da2360f..5fe5025d 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -13,8 +13,12 @@ * Updated Thu Oct 12 09:19:26 1995 by faith@cs.unc.edu with security * patches from Zefram * - * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - * to remove trailing empty fields. Oct 5, 96. + * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, + * to remove trailing empty fields. Oct 5, 96. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * * */ @@ -32,6 +36,8 @@ #include #include "my_crypt.h" #include "../version.h" +#include "nls.h" +#include "env.h" #if REQUIRE_PASSWORD && USE_PAM #include @@ -79,14 +85,14 @@ 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 */ +/* we do not accept gecos field sizes longer than MAX_FIELD_SIZE */ #define MAX_FIELD_SIZE 256 int main (argc, argv) int argc; char *argv[]; { - char *cp, *pwdstr; + char *cp; uid_t uid; struct finfo oldf, newf; boolean interactive; @@ -98,15 +104,17 @@ int main (argc, argv) struct pam_conv conv = { misc_conv, NULL }; #endif + sanitize_env(); + setlocale(LC_ALL, ""); /* both for messages and for iscntrl() below */ + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + /* whoami is the program name for error messages */ whoami = argv[0]; if (! whoami) whoami = "chfn"; 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 @@ -125,19 +133,19 @@ int main (argc, argv) if (! newf.username) { parse_passwd (getpwuid (uid), &oldf); if (! oldf.username) { - fprintf (stderr, "%s: you (user %d) don't exist.\n", whoami, uid); + fprintf (stderr, _("%s: you (user %d) don't exist.\n"), whoami, uid); return (-1); } } else { parse_passwd (getpwnam (newf.username), &oldf); if (! oldf.username) { cp = newf.username; - fprintf (stderr, "%s: user \"%s\" does not exist.\n", whoami, cp); + fprintf (stderr, _("%s: user \"%s\" does not exist.\n"), whoami, cp); return (-1); } } if (!(is_local(oldf.username))) { - fprintf (stderr, "%s: can only change local entries; use yp%s instead.\n", + fprintf (stderr, _("%s: can only change local entries; use yp%s instead.\n"), whoami, whoami); exit(1); } @@ -149,28 +157,28 @@ int main (argc, argv) return (-1); } - printf ("Changing finger information for %s.\n", oldf.username); + printf (_("Changing finger information for %s.\n"), oldf.username); #if REQUIRE_PASSWORD # if USE_PAM if(uid != 0) { if (pam_start("chfn", oldf.username, &conv, &pamh)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } if (pam_authenticate(pamh, 0)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } retcode = pam_acct_mgmt(pamh, 0); if (retcode == PAM_NEW_AUTHTOK_REQD) { retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); } else if (retcode) { - puts("Password error."); + puts(_("Password error.")); exit(1); } if (pam_setcred(pamh, 0)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } /* no need to establish a session; this isn't a session-oriented @@ -179,10 +187,10 @@ int main (argc, argv) # else /* USE_PAM */ /* require password, unless root */ if(uid != 0 && oldf.pw->pw_passwd && oldf.pw->pw_passwd[0]) { - pwdstr = getpass("Password: "); + char *pwdstr = getpass(_("Password: ")); if(strncmp(oldf.pw->pw_passwd, crypt(pwdstr, oldf.pw->pw_passwd), 13)) { - puts("Incorrect password."); + puts(_("Incorrect password.")); exit(1); } } @@ -193,7 +201,7 @@ int main (argc, argv) if (interactive) ask_info (&oldf, &newf); if (! set_changed_data (&oldf, &newf)) { - printf ("Finger information not changed.\n"); + printf (_("Finger information not changed.\n")); return 0; } status = save_new_data (&oldf); @@ -296,9 +304,9 @@ static boolean parse_argv (argc, argv, pinfo) static void usage (fp) FILE *fp; { - fprintf (fp, "Usage: %s [ -f full-name ] [ -o office ] ", whoami); - fprintf (fp, "[ -p office-phone ]\n [ -h home-phone ] "); - fprintf (fp, "[ --help ] [ --version ]\n"); + fprintf (fp, _("Usage: %s [ -f full-name ] [ -o office ] "), whoami); + fprintf (fp, _("[ -p office-phone ]\n [ -h home-phone ] ")); + fprintf (fp, _("[ --help ] [ --version ]\n")); } /* @@ -367,7 +375,7 @@ static char *prompt (question, def_val) printf("%s [%s]: ", question, def_val); *buf = 0; if (fgets (buf, sizeof (buf), stdin) == NULL) { - printf ("\nAborted.\n"); + printf (_("\nAborted.\n")); exit (-1); } /* remove the newline at the end of buf. */ @@ -400,7 +408,7 @@ static int check_gecos_string (msg, gecos) if (strlen(gecos) > MAX_FIELD_SIZE) { if (msg != NULL) printf("%s: ", msg); - printf("field is too long.\n"); + printf(_("field is too long.\n")); return -1; } @@ -408,12 +416,12 @@ static int check_gecos_string (msg, gecos) c = gecos[i]; if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { if (msg) printf ("%s: ", msg); - printf ("'%c' is not allowed.\n", c); + printf (_("'%c' is not allowed.\n"), c); return (-1); } if (iscntrl (c)) { if (msg) printf ("%s: ", msg); - printf ("Control characters are not allowed.\n"); + printf (_("Control characters are not allowed.\n")); return (-1); } } @@ -478,10 +486,10 @@ static int save_new_data (pinfo) pinfo->pw->pw_gecos = gecos; if (setpwnam (pinfo->pw) < 0) { perror ("setpwnam"); - printf( "Finger information *NOT* changed. Try again later.\n" ); + printf( _("Finger information *NOT* changed. Try again later.\n" )); return (-1); } - printf ("Finger information changed.\n"); + printf (_("Finger information changed.\n")); return 0; } @@ -495,7 +503,7 @@ static void *xmalloc (bytes) vp = malloc (bytes); if (! vp && bytes > 0) { - perror ("malloc failed"); + perror (_("malloc failed")); exit (-1); } return vp; diff --git a/login-utils/chsh.c b/login-utils/chsh.c index 8e8a51bc..f9c4d743 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -17,6 +17,10 @@ * suggestion from Zefram. Disallowing users with shells not in /etc/shells * from changing their shell. * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * + * */ #if 0 @@ -34,6 +38,8 @@ #include #include "my_crypt.h" #include "../version.h" +#include "nls.h" +#include "env.h" #if REQUIRE_PASSWORD && USE_PAM #include @@ -79,7 +85,7 @@ int main (argc, argv) int argc; char *argv[]; { - char *cp, *shell, *oldshell, *pwdstr; + char *cp, *shell, *oldshell; uid_t uid; struct sinfo info; struct passwd *pw; @@ -90,6 +96,11 @@ int main (argc, argv) struct pam_conv conv = { misc_conv, NULL }; #endif + sanitize_env(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + /* whoami is the program name for error messages */ whoami = argv[0]; if (! whoami) whoami = "chsh"; @@ -104,20 +115,19 @@ int main (argc, argv) if (! info.username) { pw = getpwuid (uid); if (! pw) { - fprintf (stderr, "%s: you (user %d) don't exist.\n", whoami, uid); + fprintf (stderr, _("%s: you (user %d) don't exist.\n"), whoami, uid); return (-1); } } else { pw = getpwnam (info.username); if (! pw) { cp = info.username; - fprintf (stderr, "%s: user \"%s\" does not exist.\n", whoami, cp); + fprintf (stderr, _("%s: user \"%s\" does not exist.\n"), whoami, cp); return (-1); } } if (!(is_local(pw->pw_name))) { - fprintf (stderr, "%s: can only change local entries; use yp%s instead.\n -", + fprintf (stderr, _("%s: can only change local entries; use yp%s instead.\n"), whoami, whoami); exit(1); } @@ -128,35 +138,35 @@ int main (argc, argv) /* reality check */ if (uid != 0 && (uid != pw->pw_uid || !get_shell_list(oldshell))) { errno = EACCES; - fprintf(stderr,"%s: Your shell is not in /etc/shells, shell change" - " denied\n",whoami); + fprintf(stderr,_("%s: Your shell is not in /etc/shells, shell change" + " denied\n"),whoami); return (-1); } shell = info.shell; - printf( "Changing shell for %s.\n", pw->pw_name ); + printf( _("Changing shell for %s.\n"), pw->pw_name ); #if REQUIRE_PASSWORD # if USE_PAM if(uid != 0) { if (pam_start("chsh", pw->pw_name, &conv, &pamh)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } if (pam_authenticate(pamh, 0)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } retcode = pam_acct_mgmt(pamh, 0); if (retcode == PAM_NEW_AUTHTOK_REQD) { retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); } else if (retcode) { - puts("Password error."); + puts(_("Password error.")); exit(1); } if (pam_setcred(pamh, 0)) { - puts("Password error."); + puts(_("Password error.")); exit(1); } /* no need to establish a session; this isn't a session-oriented @@ -165,10 +175,10 @@ int main (argc, argv) # else /* USE_PAM */ /* require password, unless root */ if(uid != 0 && pw->pw_passwd && pw->pw_passwd[0]) { - pwdstr = getpass("Password: "); + char *pwdstr = getpass(_("Password: ")); if(strncmp(pw->pw_passwd, crypt(pwdstr, pw->pw_passwd), 13)) { - puts("Incorrect password."); + puts(_("Incorrect password.")); exit(1); } } @@ -176,24 +186,24 @@ int main (argc, argv) #endif /* REQUIRE_PASSWORD */ if (! shell) { - shell = prompt ("New shell", oldshell); + shell = prompt (_("New shell"), oldshell); if (! shell) return 0; } if (check_shell (shell) < 0) return (-1); if (! strcmp (pw->pw_shell, shell)) { - printf ("Shell not changed.\n"); + printf (_("Shell not changed.\n")); return 0; } if (!strcmp(shell, "/bin/sh")) shell = ""; pw->pw_shell = shell; if (setpwnam (pw) < 0) { perror ("setpwnam"); - printf( "Shell *NOT* changed. Try again later.\n" ); + printf( _("Shell *NOT* changed. Try again later.\n") ); return (-1); } - printf ("Shell changed.\n"); + printf (_("Shell changed.\n")); return 0; } @@ -261,9 +271,9 @@ static void parse_argv (argc, argv, pinfo) static void usage (fp) FILE *fp; { - fprintf (fp, "Usage: %s [ -s shell ] ", whoami); - fprintf (fp, "[ --list-shells ] [ --help ] [ --version ]\n"); - fprintf (fp, " [ username ]\n"); + fprintf (fp, _("Usage: %s [ -s shell ] "), whoami); + fprintf (fp, _("[ --list-shells ] [ --help ] [ --version ]\n")); + fprintf (fp, _(" [ username ]\n")); } /* @@ -281,7 +291,7 @@ static char *prompt (question, def_val) printf("%s [%s]: ", question, def_val); *buf = 0; if (fgets (buf, sizeof (buf), stdin) == NULL) { - printf ("\nAborted.\n"); + printf (_("\nAborted.\n")); exit (-1); } /* remove the newline at the end of buf. */ @@ -307,44 +317,44 @@ static int check_shell (shell) int i, c; if (*shell != '/') { - printf ("%s: shell must be a full path name.\n", whoami); + printf (_("%s: shell must be a full path name.\n"), whoami); return (-1); } if (access (shell, F_OK) < 0) { - printf ("%s: \"%s\" does not exist.\n", whoami, shell); + printf (_("%s: \"%s\" does not exist.\n"), whoami, shell); return (-1); } if (access (shell, X_OK) < 0) { - printf ("%s: \"%s\" is not executable.\n", whoami, shell); + printf (_("%s: \"%s\" is not executable.\n"), whoami, shell); return (-1); } /* keep /etc/passwd clean. */ for (i = 0; i < strlen (shell); i++) { c = shell[i]; if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { - printf ("%s: '%c' is not allowed.\n", whoami, c); + printf (_("%s: '%c' is not allowed.\n"), whoami, c); return (-1); } if (iscntrl (c)) { - printf ("%s: Control characters are not allowed.\n", whoami); + printf (_("%s: Control characters are not allowed.\n"), whoami); return (-1); } } #if ONLY_LISTED_SHELLS if (! get_shell_list (shell)) { if (!getuid()) - printf ("Warning: \"%s\" is not listed in /etc/shells\n", shell); + printf (_("Warning: \"%s\" is not listed in /etc/shells\n"), shell); else { - printf ("%s: \"%s\" is not listed in /etc/shells.\n", + printf (_("%s: \"%s\" is not listed in /etc/shells.\n"), whoami, shell); - printf( "%s: use -l option to see list\n", whoami ); + printf( _("%s: use -l option to see list\n"), whoami ); exit(1); } } #else if (! get_shell_list (shell)) { - printf ("Warning: \"%s\" is not listed in /etc/shells.\n", shell); - printf( "Use %s -l to see list.\n", whoami ); + printf (_("Warning: \"%s\" is not listed in /etc/shells.\n"), shell); + printf( _("Use %s -l to see list.\n"), whoami ); } #endif return 0; @@ -365,7 +375,7 @@ static boolean get_shell_list (shell_name) found = false; fp = fopen ("/etc/shells", "r"); if (! fp) { - if (! shell_name) printf ("No known shells.\n"); + if (! shell_name) printf (_("No known shells.\n")); return true; } while (fgets (buf, sizeof (buf), fp) != NULL) { @@ -399,7 +409,7 @@ static void *xmalloc (bytes) vp = malloc (bytes); if (! vp && bytes > 0) { - perror ("malloc failed"); + perror (_("malloc failed")); exit (-1); } return vp; diff --git a/login-utils/cryptocard.c b/login-utils/cryptocard.c index b3edc6fd..1195b2eb 100644 --- a/login-utils/cryptocard.c +++ b/login-utils/cryptocard.c @@ -16,6 +16,10 @@ The sources for this code are maintained in ftp://ftp.daimi.aau.dk/pub/linux/poe/poeigl-X.XX.tar.gz + + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + */ #ifdef CRYPTOCARD @@ -40,6 +44,7 @@ #include #include #include +#include "nls.h" #ifdef KOONTZ_DES #include "../koontz-des/des.h" @@ -62,12 +67,12 @@ generate_challenge(void) /* create and present a challenge string */ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0) { - syslog(LOG_NOTICE, "couldn't open /dev/urandom"); + syslog(LOG_NOTICE, _("couldn't open /dev/urandom")); return NULL; } if (read(rfd, &clong, 4) < 4) { close(rfd); - syslog(LOG_NOTICE, "couldn't read random data from /dev/urandom"); + syslog(LOG_NOTICE, _("couldn't read random data from /dev/urandom")); return NULL; } close(rfd); @@ -90,22 +95,22 @@ get_key() sprintf(keyfile, "%s/.cryptocard", pwd->pw_dir); if ((rfd = open(keyfile, O_RDONLY)) < 0) { - syslog(LOG_NOTICE, "can't open %s for reading", keyfile); + syslog(LOG_NOTICE, _("can't open %s for reading"), keyfile); goto bail_out; } if (fstat(rfd, &statbuf) < 0) { - syslog(LOG_NOTICE, "can't stat(%s)", keyfile); + syslog(LOG_NOTICE, _("can't stat(%s)"), keyfile); goto close_and_bail_out; } if ((statbuf.st_uid != pwd->pw_uid) || ((statbuf.st_mode & S_IFMT) != S_IFREG) || (statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) { - syslog(LOG_NOTICE, "%s doesn't have the correct filemodes", keyfile); + syslog(LOG_NOTICE, _("%s doesn't have the correct filemodes"), keyfile); goto close_and_bail_out; } if (read(rfd, key, 8) < 8) { - syslog(LOG_NOTICE, "can't read data from %s", keyfile); + syslog(LOG_NOTICE, _("can't read data from %s"), keyfile); goto close_and_bail_out; } diff --git a/login-utils/islocal.c b/login-utils/islocal.c index 5480c574..10a709b5 100644 --- a/login-utils/islocal.c +++ b/login-utils/islocal.c @@ -10,11 +10,16 @@ to distinguish user names where one is a prefix of the other, and to use "pathnames.h". Oct 5, 96. + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + + */ #include #include +#include "nls.h" #include "pathnames.h" #define MAX_LENGTH 1024 @@ -28,7 +33,7 @@ is_local(char *user) int len; if(!(fd = fopen(_PATH_PASSWD, "r"))) { - fprintf(stderr,"Can't read %s, exiting.",_PATH_PASSWD); + fprintf(stderr,_("Can't read %s, exiting."),_PATH_PASSWD); exit(1); } diff --git a/login-utils/last.c b/login-utils/last.c index cf59b8ea..b78d00b8 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -18,12 +18,17 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ + /* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + /* * last */ #include #include #include +#include #include #include #include @@ -32,18 +37,23 @@ #include #include #include + +#include +#include #include + #include "pathnames.h" +#include "nls.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 */ +static struct utmp utmpbuf; -#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 */ +#define HMAX (int)sizeof(utmpbuf.ut_host) /* size of utmp host field */ +#define LMAX (int)sizeof(utmpbuf.ut_line) /* size of utmp tty field */ +#define NMAX (int)sizeof(utmpbuf.ut_name) /* size of utmp name field */ #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -94,6 +104,10 @@ main(argc, argv) extern char *optarg; int ch; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + while ((ch = getopt(argc, argv, "0123456789yli:f:h:t:")) != EOF) switch((char)ch) { case '0': case '1': case '2': case '3': case '4': @@ -126,7 +140,7 @@ main(argc, argv) break; case '?': default: - fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr); + fputs(_("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n"), stderr); exit(1); } for (argv += optind; *argv; ++argv) { @@ -183,31 +197,39 @@ 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; + long delta; /* time difference */ void onintr(); - char *ct, *crmsg = NULL; + char *crmsg = NULL; + char *ct = NULL; + struct utmp **utmplist = NULL; + int listlen = 0; + int listnr = 0; + int i; + + utmpname(file); + + (void)time(&utmpbuf.ut_time); + (void)signal(SIGINT, onintr); + (void)signal(SIGQUIT, onintr); - if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) { - perror(file); - exit(1); + setutent(); + while((bp = getutent())) { + if(listnr >= listlen) { + listlen += 10; + listlen *= 2; /* avoid quadratic behaviour */ + utmplist = realloc(utmplist, sizeof(bp) * listlen); + } + + utmplist[listnr] = malloc(sizeof(*bp)); + memcpy(utmplist[listnr++], bp, sizeof(*bp)); } - bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf); + endutent(); - (void)time(&buf[0].ut_time); - (void)signal(SIGINT, onintr); - (void)signal(SIGQUIT, onintr); + if(listnr) + ct = ctime(&utmplist[0]->ut_time); - while (--bl >= 0) { - 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); - exit(1); - } - for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) { + for(i = listnr - 1; i >= 0; i--) { + bp = utmplist[i]; /* * if the terminal line is '~', the machine stopped. * see utmp(5) for more info. @@ -258,7 +280,7 @@ wtmp() print_partial_line(bp); if (!T->logout) - puts(" still logged in"); + puts(_(" still logged in")); else { if (T->logout < 0) { T->logout = -T->logout; @@ -276,10 +298,11 @@ wtmp() return; } T->logout = bp->ut_time; - } + utmpbuf.ut_time = bp->ut_time; + free(bp); } - ct = ctime(&buf[0].ut_time); - printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); + if(utmplist) free(utmplist); + if(ct) printf(_("\nwtmp begins %s"), ct); /* ct already ends in \n */ } /* @@ -293,7 +316,7 @@ want(bp, check) { register ARG *step; - if (check) + 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 @@ -303,6 +326,7 @@ want(bp, check) bp->ut_line[3] = '\0'; else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1)) bp->ut_line[4] = '\0'; + } if (!arglist) return(YES); @@ -340,7 +364,7 @@ addarg(type, arg) register ARG *cur; if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) { - fputs("last: malloc failure.\n", stderr); + fputs(_("last: malloc failure.\n"), stderr); exit(1); } cur->next = arglist; @@ -360,7 +384,7 @@ addtty(ttyname) register TTY *cur; if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) { - fputs("last: malloc failure.\n", stderr); + fputs(_("last: malloc failure.\n"), stderr); exit(1); } cur->next = ttylist; @@ -389,7 +413,7 @@ hostconv(arg) if (first) { first = 0; if (gethostname(name, sizeof(name))) { - perror("last: gethostname"); + perror(_("last: gethostname")); exit(1); } hostdot = strchr(name, '.'); @@ -415,7 +439,7 @@ ttyconv(arg) if (strlen(arg) == 2) { /* either 6 for "ttyxx" or 8 for "console" */ if (!(mval = malloc((unsigned int)8))) { - fputs("last: malloc failure.\n", stderr); + fputs(_("last: malloc failure.\n"), stderr); exit(1); } if (!strcmp(arg, "co")) @@ -441,8 +465,8 @@ onintr(signo) { char *ct; - ct = ctime(&buf[0].ut_time); - printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); + ct = ctime(&utmpbuf.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 a2acbd9f..88bb4d89 100644 --- a/login-utils/login.1 +++ b/login-utils/login.1 @@ -25,7 +25,7 @@ If the user is .I not root, and if .I /etc/nologin -exists, the contents of of this file are printed to the screen, and the +exists, the contents of this file are printed to the screen, and the login is terminated. This is typically used to prevent logins when the system is being taken down. @@ -243,7 +243,8 @@ 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 @@ -307,6 +308,16 @@ The undocumented BSD option is not supported. This may be required by some .BR rlogind (8) programs. + +A recursive login, as used to be possible in the good old days, +no longer works; for most purposes +.BR su (1) +is a satisfactory substitute. Indeed, for security reasons, +login does a vhangup() system call to remove any possible +listening processes on the tty. This is to avoid password +sniffing. If one uses the command "login", then the surrounding shell +gets killed by vhangup() because it's no longer the true owner of the tty. +This can be avoided by using "exec login" in a top-level shell or xterm. .SH AUTHOR Derived from BSD login 5.40 (5/9/89) by Michael Glad (glad@daimi.dk) for HP-UX diff --git a/login-utils/login.c b/login-utils/login.c index c742af75..fa045016 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -51,6 +51,11 @@ 1992-02-05 poe@daimi.aau.dk: Ported the stuff to Linux 0.12 From 1992 till now (1997) this code for Linux has been maintained at ftp.daimi.aau.dk:/pub/linux/poe/ + + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + Sun Mar 21 1999 - Arnaldo Carvalho de Melo + - fixed strerr(errno) in gettext calls */ /* @@ -112,6 +117,7 @@ #include #include #include "my_crypt.h" +#include "nls.h" #ifdef __linux__ # include @@ -275,7 +281,7 @@ main(int argc, char **argv) struct group *gr; register int ch; register char *p; - int ask, fflag, hflag, pflag, cnt; + int ask, fflag, hflag, pflag, cnt, errsv; int quietlog, passwd_req; char *domain, *ttyn; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; @@ -292,7 +298,6 @@ main(int argc, char **argv) pam_handle_t *pamh = NULL; struct pam_conv conv = { misc_conv, NULL }; pid_t childPid; - void (*oldSigHandler) (); #else char *salt, *pp; #endif @@ -304,6 +309,10 @@ main(int argc, char **argv) alarm((unsigned int)timeout); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); setpriority(PRIO_PROCESS, 0, 0); #ifdef HAVE_QUOTA @@ -337,14 +346,14 @@ main(int argc, char **argv) case 'h': if (getuid()) { fprintf(stderr, - "login: -h for super-user only.\n"); + _("login: -h for super-user only.\n")); exit(1); } hflag = 1; if (domain && (p = index(optarg, '.')) && strcasecmp(p, domain) == 0) *p = 0; - hostname = optarg; + hostname = strdup(optarg); /* strdup: Ambrose C. Li */ { struct hostent *he = gethostbyname(hostname); if (he) { @@ -362,7 +371,7 @@ main(int argc, char **argv) case '?': default: fprintf(stderr, - "usage: login [-fp] [username]\n"); + _("usage: login [-fp] [username]\n")); exit(1); } argc -= optind; @@ -450,6 +459,12 @@ main(int argc, char **argv) openlog("login", LOG_ODELAY, LOG_AUTHPRIV); +#if 0 + /* other than iso-8859-1 */ + printf("\033(K"); + fprintf(stderr,"\033(K"); +#endif + #ifdef USE_PAM /* username is initialized to NULL and if specified on the command line it is set. @@ -458,9 +473,9 @@ main(int argc, char **argv) retcode = pam_start("login",username, &conv, &pamh); if(retcode != PAM_SUCCESS) { - fprintf(stderr,"login: PAM Failure, aborting: %s\n", + fprintf(stderr,_("login: PAM Failure, aborting: %s\n"), pam_strerror(pamh, retcode)); - syslog(LOG_ERR,"Couldn't initialize PAM: %s", pam_strerror(pamh, retcode)); + syslog(LOG_ERR,_("Couldn't initialize PAM: %s"), pam_strerror(pamh, retcode)); exit(99); } /* hostname & tty are either set to NULL or their correct values, @@ -469,6 +484,15 @@ main(int argc, char **argv) PAM_FAIL_CHECK; retcode = pam_set_item(pamh, PAM_TTY, tty); PAM_FAIL_CHECK; + +#if 0 + /* other than iso-8859-1 + * one more time due to reset tty by PAM + */ + printf("\033(K"); + fprintf(stderr,"\033(K"); +#endif + /* if fflag == 1, then the user has already been authenticated */ if (fflag && (getuid() == 0)) passwd_req = 0; @@ -491,9 +515,9 @@ main(int argc, char **argv) (retcode == PAM_CRED_INSUFFICIENT) || (retcode == PAM_AUTHINFO_UNAVAIL))) { pam_get_item(pamh, PAM_USER, (const void **) &username); - syslog(LOG_NOTICE,"FAILED LOGIN %d FROM %s FOR %s, %s", + syslog(LOG_NOTICE,_("FAILED LOGIN %d FROM %s FOR %s, %s"), failcount, hostname, username, pam_strerror(pamh, retcode)); - fprintf(stderr,"Login incorrect\n\n"); + fprintf(stderr,_("Login incorrect\n\n")); pam_set_item(pamh,PAM_USER,NULL); retcode = pam_authenticate(pamh, 0); } @@ -502,14 +526,14 @@ main(int argc, char **argv) pam_get_item(pamh, PAM_USER, (const void **) &username); if (retcode == PAM_MAXTRIES) - syslog(LOG_NOTICE,"TOO MANY LOGIN TRIES (%d) FROM %s FOR " - "%s, %s", failcount, hostname, username, + syslog(LOG_NOTICE,_("TOO MANY LOGIN TRIES (%d) FROM %s FOR " + "%s, %s"), failcount, hostname, username, pam_strerror(pamh, retcode)); else - syslog(LOG_NOTICE,"FAILED LOGIN SESSION FROM %s FOR %s, %s", + syslog(LOG_NOTICE,_("FAILED LOGIN SESSION FROM %s FOR %s, %s"), hostname, username, pam_strerror(pamh, retcode)); - fprintf(stderr,"\nLogin incorrect\n"); + fprintf(stderr,_("\nLogin incorrect\n")); pam_end(pamh, retcode); exit(0); } @@ -558,7 +582,7 @@ main(int argc, char **argv) Feb 95 */ if (username[0] == '+') { - puts("Illegal username"); + puts(_("Illegal username")); badlogin(username); sleepexit(1); } @@ -601,16 +625,16 @@ main(int argc, char **argv) */ if (pwd && pwd->pw_uid == 0 && !rootterm(tty)) { fprintf(stderr, - "%s login refused on this terminal.\n", + _("%s login refused on this terminal.\n"), pwd->pw_name); if (hostname) syslog(LOG_NOTICE, - "LOGIN %s REFUSED FROM %s ON TTY %s", + _("LOGIN %s REFUSED FROM %s ON TTY %s"), pwd->pw_name, hostname, tty); else syslog(LOG_NOTICE, - "LOGIN %s REFUSED ON TTY %s", + _("LOGIN %s REFUSED ON TTY %s"), pwd->pw_name, tty); continue; } @@ -623,7 +647,7 @@ main(int argc, char **argv) break; setpriority(PRIO_PROCESS, 0, -4); - pp = getpass("Password: "); + pp = getpass(_("Password: ")); # ifdef CRYPTOCARD if (strncmp(pp, "CRYPTO", 6) == 0) { @@ -662,7 +686,7 @@ main(int argc, char **argv) if (pwd && !strcmp(p, pwd->pw_passwd)) break; - printf("Login incorrect\n"); + printf(_("Login incorrect\n")); badlogin(username); /* log ALL bad logins */ failures++; @@ -684,11 +708,11 @@ main(int argc, char **argv) switch(errno) { case EUSERS: fprintf(stderr, - "Too many users logged on already.\nTry again later.\n"); + _("Too many users logged on already.\nTry again later.\n")); break; case EPROCLIM: fprintf(stderr, - "You have too many processes running.\n"); + _("You have too many processes running.\n")); break; default: perror("quota (Q_SETUID)"); @@ -734,7 +758,7 @@ main(int argc, char **argv) #ifndef __linux__ # ifdef KERBEROS if (notickets && !quietlog) - printf("Warning: no Kerberos tickets issued\n"); + printf(_("Warning: no Kerberos tickets issued\n")); # endif # ifndef USE_PAM /* PAM does all of this for us */ @@ -746,13 +770,13 @@ main(int argc, char **argv) if (pwd->pw_change) { if (tp.tv_sec >= pwd->pw_change) { - printf("Sorry -- your password has expired.\n"); + printf(_("Sorry -- your password has expired.\n")); sleepexit(1); } else if (tp.tv_sec - pwd->pw_change < TWOWEEKS && !quietlog) { struct tm *ttp; ttp = localtime(&pwd->pw_change); - printf("Warning: your password expires on %s %d, %d\n", + printf(_("Warning: your password expires on %s %d, %d\n"), months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); } @@ -760,13 +784,13 @@ main(int argc, char **argv) if (pwd->pw_expire) { if (tp.tv_sec >= pwd->pw_expire) { - printf("Sorry -- your account has expired.\n"); + printf(_("Sorry -- your account has expired.\n")); sleepexit(1); } else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS && !quietlog) { struct tm *ttp; ttp = localtime(&pwd->pw_expire); - printf("Warning: your account expires on %s %d, %d\n", + printf(_("Warning: your account expires on %s %d, %d\n"), months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); } @@ -796,7 +820,6 @@ main(int argc, char **argv) struct utmp ut; int wtmp; struct utmp *utp; - time_t t; pid_t mypid = getpid(); utmpname(_PATH_UTMP); @@ -814,6 +837,16 @@ Michael Riepe && utp->ut_type >= INIT_PROCESS && utp->ut_type <= DEAD_PROCESS) break; + + /* If we can't find a pre-existing entry by pid, try by line. + BSD network daemons may rely on this. (anonymous) */ + if (utp == NULL) { + setutent(); + ut.ut_type = LOGIN_PROCESS; + strncpy(ut.ut_id, ttyn + 8, sizeof(ut.ut_id)); + strncpy(ut.ut_line, ttyn + 5, sizeof(ut.ut_line)); + utp = getutid(&ut); + } if (utp) { memcpy(&ut, utp, sizeof(ut)); @@ -821,7 +854,6 @@ Michael Riepe /* some gettys/telnetds don't initialize utmp... */ memset(&ut, 0, sizeof(ut)); } - /* endutent(); superfluous, error for glibc */ if (ut.ut_id[0] == 0) strncpy(ut.ut_id, ttyn + 8, sizeof(ut.ut_id)); @@ -829,9 +861,16 @@ Michael Riepe strncpy(ut.ut_user, username, sizeof(ut.ut_user)); strncpy(ut.ut_line, ttyn + 5, sizeof(ut.ut_line)); ut.ut_line[sizeof(ut.ut_line)-1] = 0; - time(&t); - ut.ut_time = t; /* ut_time is not always a time_t */ - /* (we might test #ifdef _HAVE_UT_TV ) */ +#ifdef _HAVE_UT_TV /* in included by */ + gettimeofday(&ut.ut_tv, NULL); +#else + { + time_t t; + time(&t); + ut.ut_time = t; /* ut_time is not always a time_t */ + /* glibc2 #defines it as ut_tv.tv_sec */ + } +#endif ut.ut_type = USER_PROCESS; ut.ut_pid = mypid; if (hostname) { @@ -985,23 +1024,23 @@ Michael Riepe #endif if (tty[sizeof("tty")-1] == 'S') - syslog(LOG_INFO, "DIALUP AT %s BY %s", tty, pwd->pw_name); + syslog(LOG_INFO, _("DIALUP AT %s BY %s"), tty, pwd->pw_name); /* allow tracking of good logins. -steve philp (sphilp@mail.alliance.net) */ if (pwd->pw_uid == 0) { if (hostname) - syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", + syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"), tty, hostname); else - syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); + syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), tty); } else { if (hostname) - syslog(LOG_INFO, "LOGIN ON %s BY %s FROM %s", tty, + syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"), tty, pwd->pw_name, hostname); else - syslog(LOG_INFO, "LOGIN ON %s BY %s", tty, + syslog(LOG_INFO, _("LOGIN ON %s BY %s"), tty, pwd->pw_name); } @@ -1012,8 +1051,8 @@ Michael Riepe motd(); 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 " : ""); + printf(_("You have %smail.\n"), + (st.st_mtime > st.st_atime) ? _("new ") : ""); } } @@ -1029,8 +1068,9 @@ Michael Riepe signal(SIGINT, SIG_IGN); childPid = fork(); if (childPid < 0) { + int errsv = errno; /* error in fork() */ - fprintf(stderr,"login: failure forking: %s", strerror(errno)); + fprintf(stderr,_("login: failure forking: %s"), strerror(errsv)); PAM_END; exit(0); } else if (childPid) { @@ -1045,17 +1085,17 @@ Michael Riepe /* 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"); + syslog(LOG_ALERT, _("setuid() failed")); exit(1); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { - printf("No directory %s!\n", pwd->pw_dir); + printf(_("No directory %s!\n"), pwd->pw_dir); if (chdir("/")) exit(0); pwd->pw_dir = "/"; - printf("Logging in with home = \"/\".\n"); + printf(_("Logging in with home = \"/\".\n")); } /* if the shell field has a space: treat it like a shell script */ @@ -1063,7 +1103,7 @@ Michael Riepe buff = malloc(strlen(pwd->pw_shell) + 6); if (!buff) { - fprintf(stderr, "login: no memory for shell script.\n"); + fprintf(stderr, _("login: no memory for shell script.\n")); exit(0); } @@ -1088,11 +1128,13 @@ Michael Riepe execvp(childArgv[0], childArgv + 1); - if (!strcmp(childArgv[0], "/bin/sh")) - fprintf(stderr, "login: couldn't exec shell script: %s.\n", - strerror(errno)); + errsv = errno; + + if (!strcmp(childArgv[0], "/bin/sh")) + fprintf(stderr, _("login: couldn't exec shell script: %s.\n"), + strerror(errsv)); else - fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); + fprintf(stderr, _("login: no shell: %s.\n"), strerror(errsv)); exit(0); } @@ -1108,7 +1150,7 @@ getloginname() cnt2 = 0; for (;;) { cnt = 0; - printf("\n%s login: ", thishost); fflush(stdout); + printf(_("\n%s login: "), thishost); fflush(stdout); for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin("EOF"); @@ -1119,15 +1161,15 @@ getloginname() cnt++; if (cnt > UT_NAMESIZE + 20) { - fprintf(stderr, "login name much too long.\n"); - badlogin("NAME too long"); + fprintf(stderr, _("login name much too long.\n")); + badlogin(_("NAME too long")); exit(0); } } if (p > nbuf) { if (nbuf[0] == '-') fprintf(stderr, - "login names may not start with '-'.\n"); + _("login names may not start with '-'.\n")); else { *p = '\0'; username = nbuf; @@ -1137,8 +1179,8 @@ getloginname() cnt2++; if (cnt2 > 50) { - fprintf(stderr, "too many bare linefeeds.\n"); - badlogin("EXCESSIVE linefeeds"); + fprintf(stderr, _("too many bare linefeeds.\n")); + badlogin(_("EXCESSIVE linefeeds")); exit(0); } } @@ -1149,7 +1191,7 @@ timedout() { struct termio ti; - fprintf(stderr, "Login timed out after %d seconds\n", timeout); + fprintf(stderr, _("Login timed out after %d seconds\n"), timeout); /* reset echo */ ioctl(0, TCGETA, &ti); @@ -1171,7 +1213,7 @@ rootterm(ttyn) { int fd; char buf[100],*p; - int cnt, more; + int cnt, more = 0; fd = open(SECURETTY, O_RDONLY); if(fd < 0) return 1; @@ -1249,14 +1291,14 @@ dolastlog(quiet) if (!quiet) { if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) { - printf("Last login: %.*s ", + printf(_("Last login: %.*s "), 24-5, (char *)ctime(&ll.ll_time)); if (*ll.ll_host != '\0') - printf("from %.*s\n", + printf(_("from %.*s\n"), (int)sizeof(ll.ll_host), ll.ll_host); else - printf("on %.*s\n", + printf(_("on %.*s\n"), (int)sizeof(ll.ll_line), ll.ll_line); } lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); @@ -1277,12 +1319,21 @@ dolastlog(quiet) void badlogin(const char *name) { - if (hostname) - syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", - failures, failures > 1 ? "S" : "", hostname, name); - else - syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", - failures, failures > 1 ? "S" : "", tty, name); + if (failures == 1) { + if (hostname) + syslog(LOG_NOTICE, _("LOGIN FAILURE FROM %s, %s"), + hostname, name); + else + syslog(LOG_NOTICE, _("LOGIN FAILURE ON %s, %s"), + tty, name); + } else { + if (hostname) + syslog(LOG_NOTICE, _("%d LOGIN FAILURES FROM %s, %s"), + failures, hostname, name); + else + syslog(LOG_NOTICE, _("%d LOGIN FAILURES ON %s, %s"), + failures, tty, name); + } } #undef UNKNOWN diff --git a/login-utils/mesg.c b/login-utils/mesg.c index d05d333c..cc8c4010 100644 --- a/login-utils/mesg.c +++ b/login-utils/mesg.c @@ -38,6 +38,10 @@ * Modified Fri Mar 10 20:27:19 1995, faith@cs.unc.edu, for Linux * Modified Mon Jul 1 18:14:10 1996, janl@ifi.uio.no, writing to stdout * as suggested by Michael Meskes + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * * */ @@ -50,6 +54,7 @@ #include #include #include +#include "nls.h" int main(argc, argv) @@ -60,6 +65,11 @@ main(argc, argv) char *tty; int ch; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((ch = getopt(argc, argv, "")) != EOF) switch (ch) { case '?': @@ -76,10 +86,10 @@ main(argc, argv) if (*argv == NULL) { if (sb.st_mode & (S_IWGRP | S_IWOTH)) { - (void)fprintf(stdout, "is y\n"); + (void)fprintf(stdout, _("is y\n")); exit(0); } - (void)fprintf(stdout, "is n\n"); + (void)fprintf(stdout, _("is n\n")); exit(1); } @@ -99,6 +109,6 @@ main(argc, argv) exit(1); } -usage: (void)fprintf(stderr, "usage: mesg [y | n]\n"); +usage: (void)fprintf(stderr, _("usage: mesg [y | n]\n")); exit(2); } diff --git a/login-utils/newgrp.c b/login-utils/newgrp.c index 5c26a4a0..1f8be95f 100644 --- a/login-utils/newgrp.c +++ b/login-utils/newgrp.c @@ -3,6 +3,10 @@ /* Vesa Roukonen added code for asking password */ /* Currently maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/ */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + #include #include #include @@ -11,6 +15,7 @@ #include #include "pathnames.h" #include "my_crypt.h" +#include "nls.h" #ifndef TRUE # define TRUE 1 @@ -39,7 +44,7 @@ allow_setgid(struct passwd *pe, struct group *ge) if(ge->gr_passwd && ge->gr_passwd[0] != 0) { if(strcmp(ge->gr_passwd, - crypt(getpass("Password: "), ge->gr_passwd)) == 0) { + crypt(getpass(_("Password: ")), ge->gr_passwd)) == 0) { return TRUE; /* password accepted */ } } @@ -53,9 +58,13 @@ main(int argc, char *argv[]) struct passwd *pw_entry; struct group *gr_entry; char *shell; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); if (!(pw_entry = getpwuid(getuid()))) { - perror("newgrp: Who are you?"); + perror(_("newgrp: Who are you?")); exit(1); } @@ -63,34 +72,34 @@ main(int argc, char *argv[]) if (argc < 2) { if(setgid(pw_entry->pw_gid) < 0) { - perror("newgrp: setgid"); + perror(_("newgrp: setgid")); exit(1); } } else { if (!(gr_entry = getgrnam(argv[1]))) { - perror("newgrp: No such group."); + perror(_("newgrp: No such group.")); exit(1); } else { if(allow_setgid(pw_entry, gr_entry)) { if(setgid(gr_entry->gr_gid) < 0) { - perror("newgrp: setgid"); + perror(_("newgrp: setgid")); exit(1); } } else { - puts("newgrp: Permission denied"); + puts(_("newgrp: Permission denied")); exit(1); } } } if(setuid(getuid()) < 0) { - perror("newgrp: setuid"); + perror(_("newgrp: setuid")); exit(1); } fflush(stdout); fflush(stderr); execl(shell,shell,(char*)0); - perror("No shell"); + perror(_("No shell")); fflush(stderr); exit(1); } diff --git a/login-utils/passwd.c b/login-utils/passwd.c index 0057a283..90054ccc 100644 --- a/login-utils/passwd.c +++ b/login-utils/passwd.c @@ -38,6 +38,12 @@ * auth.warning. (Of course, the password itself is not logged.) */ + /* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * Sun Mar 21 1999 - Arnaldo Carvalho de Melo + * - fixed strerr(errno) in gettext calls + */ + /* * Usage: passwd [username [password]] * Only root may use the one and two argument forms. @@ -59,12 +65,10 @@ #include #include #include "my_crypt.h" +#include "nls.h" +#include "env.h" -#if 0 -# include "../version.h" -#else -char version[] = "admutil 1.18, 15-Oct-95"; -#endif +#include "../version.h" #ifndef _PATH_CHFN # define _PATH_CHFN "/usr/bin/chfn" @@ -156,7 +160,7 @@ int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) char *c, *g, *p; if ( (strlen(passwd) < 6) ) { - printf("The password must have at least 6 characters, try again.\n"); + printf(_("The password must have at least 6 characters, try again.\n")); return 0; } @@ -169,19 +173,19 @@ int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) } if ( (other + digit + ucase + lcase) < 2) { - printf("The password must contain characters out of two of the following\n"); - printf("classes: upper and lower case letters, digits and non alphanumeric\n"); - printf("characters. See passwd(1) for more information.\n"); + printf(_("The password must contain characters out of two of the following\n")); + printf(_("classes: upper and lower case letters, digits and non alphanumeric\n")); + printf(_("characters. See passwd(1) for more information.\n")); return 0; } if ( oldpasswd[0] && !strncmp(oldpasswd, crypt(passwd, oldpasswd), 13) ) { - printf("You cannot reuse the old password.\n"); + printf(_("You cannot reuse the old password.\n")); return 0; } if ( !check_passwd_string(passwd, user) ) { - printf("Please don't use something like your username as password!\n"); + printf(_("Please don't use something like your username as password!\n")); return 0; } @@ -192,14 +196,14 @@ int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) g[c-gecos] = 0; while ( (c=rindex(g, ' ')) ) { if ( !check_passwd_string(passwd, c+1) ) { - printf("Please don't use something like your realname as password!\n"); + printf(_("Please don't use something like your realname as password!\n")); free (g); return 0; } *c = '\0'; } /* while */ if ( !check_passwd_string(passwd, g) ) { - printf("Please don't use something like your realname as password!\n"); + printf(_("Please don't use something like your realname as password!\n")); free (g); return 0; } @@ -216,8 +220,8 @@ int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) void usage() { - printf ("Usage: passwd [username [password]]\n"); - printf("Only root may use the one and two argument forms.\n"); + printf (_("Usage: passwd [username [password]]\n")); + printf(_("Only root may use the one and two argument forms.\n")); } int @@ -248,6 +252,11 @@ main(argc, argv) {0, 0, 0, 0} }; + sanitize_env(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + optind = 0; while ( (c = getopt_long(argc, argv, "foqsvV", long_options, &opt_index)) != -1 ) { switch (c) { @@ -265,17 +274,17 @@ main(argc, argv) break; case 'V': case 'v': - printf("%s\n", version); + printf("%s\n", util_linux_version); exit(0); default: - fprintf(stderr, "Usage: passwd [-foqsvV] [user [password]]\n"); + fprintf(stderr, _("Usage: passwd [-foqsvV] [user [password]]\n")); exit(1); } /* switch (c) */ } /* while */ if (fullname || shell) { char *args[100]; - int i, j; + int i, j, errsv; setuid(getuid()); /* drop special privs. */ if (fullname) @@ -288,29 +297,33 @@ main(argc, argv) args[j] = NULL; execv(args[0], args); - fprintf(stderr, "Can't exec %s: %s\n", args[0], strerror(errno)); + errsv = errno; + fprintf(stderr, _("Can't exec %s: %s\n"), args[0], strerror(errsv)); exit(1); } switch (argc - optind) { case 0: - if ( !(user = getlogin()) ) { + /* Why use getlogin()? Some systems allow having several + usernames with the same uid, especially several root accounts. + One changes the password for the username, not the uid. */ + if ( !(user = getlogin()) || !*user ) { if ( !(pe = getpwuid( getuid() )) ) { - pexit("Cannot find login name"); + pexit(_("Cannot find login name")); } else user = pe->pw_name; } break; case 1: if(gotuid) { - printf("Only root can change the password for others.\n"); + printf(_("Only root can change the password for others.\n")); exit (1); } else user = argv[optind]; break; case 2: if(gotuid) { - printf("Only root can change the password for others.\n"); + printf(_("Only root can change the password for others.\n")); exit(1); } else { user = argv[optind]; @@ -318,33 +331,33 @@ main(argc, argv) } break; default: - printf("Too many arguments.\n"); + printf(_("Too many arguments.\n")); exit (1); } /* switch */ if(!(pe = getpwnam(user))) { - pexit("Can't find username anywhere. Is `%s' really a user?", user); + pexit(_("Can't find username anywhere. Is `%s' really a user?"), user); } if (!(is_local(user))) { - puts("Sorry, I can only change local passwords. Use yppasswd instead."); + puts(_("Sorry, I can only change local passwords. Use yppasswd instead.")); exit(1); } /* if somebody got into changing utmp... */ if(gotuid && gotuid != pe->pw_uid) { - puts("UID and username does not match, imposter!"); + puts(_("UID and username does not match, imposter!")); exit(1); } if ( !silent ) - printf( "Changing password for %s\n", user ); + printf( _("Changing password for %s\n"), user ); if ( (gotuid && pe->pw_passwd && pe->pw_passwd[0]) || (!gotuid && !strcmp(user,"root")) ) { - oldstr = getpass("Enter old password: "); + oldstr = getpass(_("Enter old password: ")); if(strncmp(pe->pw_passwd, crypt(oldstr, pe->pw_passwd), 13)) { - puts("Illegal password, imposter."); + puts(_("Illegal password, imposter.")); exit(1); } } @@ -356,9 +369,9 @@ main(argc, argv) /* password not set on command line by root, ask for it ... */ redo_it: - pwdstr = getpass("Enter new password: "); + pwdstr = getpass(_("Enter new password: ")); if (pwdstr[0] == '\0') { - puts("Password not changed."); + puts(_("Password not changed.")); exit(1); } @@ -368,10 +381,10 @@ main(argc, argv) strncpy(pwdstr1, pwdstr, 9); pwdstr1[9] = 0; - pwdstr = getpass("Re-type new password: "); + pwdstr = getpass(_("Re-type new password: ")); if(strncmp(pwdstr, pwdstr1, 8)) { - puts("You misspelled it. Password not changed."); + puts(_("You misspelled it. Password not changed.")); exit(1); } } /* pwdstr i.e. password set on command line */ @@ -386,28 +399,28 @@ main(argc, argv) #ifdef LOGALL openlog("passwd", 0, LOG_AUTH); if (gotuid) - syslog(LOG_NOTICE,"password changed, user %s",user); + syslog(LOG_NOTICE,_("password changed, user %s"),user); else { if ( !strcmp(user, "root") ) - syslog(LOG_WARNING,"ROOT PASSWORD CHANGED"); + syslog(LOG_WARNING,_("ROOT PASSWORD CHANGED")); else - syslog(LOG_NOTICE,"password changed by root, user %s",user); + syslog(LOG_NOTICE,_("password changed by root, user %s"),user); } closelog(); #endif /* LOGALL */ pe->pw_passwd = cryptstr; #ifdef DEBUG - printf ("calling setpwnam to set password.\n"); + printf (_("calling setpwnam to set password.\n")); #else if (setpwnam( pe ) < 0) { perror( "setpwnam" ); - printf( "Password *NOT* changed. Try again later.\n" ); + printf( _("Password *NOT* changed. Try again later.\n" )); exit( 1 ); } #endif if ( !silent ) - printf("Password changed.\n"); + printf(_("Password changed.\n")); exit(0); } diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c index 1f1067cf..8631e7ad 100644 --- a/login-utils/setpwnam.c +++ b/login-utils/setpwnam.c @@ -41,6 +41,7 @@ * $Author: poer $ * $Revision: 1.13 $ * $Date: 1997/06/23 08:26:29 $ + * */ #undef DEBUG diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c index 8ba13b64..7ccb748a 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -27,6 +27,10 @@ * * Changes by Richard Gooch (butchered by aeb) * introducing shutdown.conf. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -48,6 +52,7 @@ #include #include "linux_reboot.h" #include "pathnames.h" +#include "nls.h" static void usage(), int_handler(), write_user(struct utmp *); static void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); @@ -69,6 +74,7 @@ char halt_action[256]; /* to find out what to do upon halt */ /* #define DEBUGGING */ #define WR(s) write(fd, s, strlen(s)) +#define WRCRLF write(fd, "\r\n", 2) #define ERRSTRING sys_errlist[errno] @@ -76,7 +82,7 @@ void usage() { fprintf(stderr, - "Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n"); + _("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n")); exit(1); } @@ -94,7 +100,7 @@ int_handler() { unlink(_PATH_NOLOGIN); signal(SIGINT, SIG_DFL); - my_puts("Shutdown process aborted"); + my_puts(_("Shutdown process aborted")); exit(1); } @@ -110,9 +116,13 @@ main(int argc, char *argv[]) int fd; char *ptr; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + #ifndef DEBUGGING if(geteuid()) { - fprintf(stderr, "%s: Only root can shut a system down.\n", + fprintf(stderr, _("%s: Only root can shut a system down.\n"), argv[0]); exit(1); } @@ -206,8 +216,8 @@ main(int argc, char *argv[]) then = 3600 * hour + 60 * minute; timeout = then - now; if(timeout < 0) { - fprintf(stderr, "That must be tomorrow, " - "can't you wait till then?\n"); + fprintf(stderr, _("That must be tomorrow, " + "can't you wait till then?\n")); exit(1); } } else { @@ -233,6 +243,9 @@ main(int argc, char *argv[]) if (fgets (line, sizeof(line), fp) != NULL && strncasecmp (line, "HALT_ACTION", 11) == 0 && iswhitespace(line[11])) { + p = index(line, '\n'); + if (p) + *p = 0; /* strip final '\n' */ p = line+11; while(iswhitespace(*p)) p++; @@ -255,16 +268,16 @@ main(int argc, char *argv[]) } *ptr = '\0'; } else if (!opt_msgset) { - strcpy(message, "for maintenance; bounce, bounce"); + strcpy(message, _("for maintenance; bounce, bounce")); } #ifdef DEBUGGING - printf("timeout = %d, quiet = %d, reboot = %d\n", + printf(_("timeout = %d, quiet = %d, reboot = %d\n"), timeout, opt_quiet, opt_reboot); #endif /* so much for option-processing, now begin termination... */ - if(!(whom = getlogin())) whom = "ghost"; + if(!(whom = getlogin()) || !*whom) whom = "ghost"; if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */ setpriority(PRIO_PROCESS, 0, PRIO_MIN); @@ -282,9 +295,14 @@ main(int argc, char *argv[]) if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) { - WR("\r\nThe system is being shut down within 5 minutes\r\n"); + /* keep xgettext happy and leave \r\n outside strings */ + WRCRLF; + WR(_("The system is being shut down within 5 minutes")); + WRCRLF; write(fd, message, strlen(message)); - WR("\r\nLogin is therefore prohibited.\r\n"); + WRCRLF; + WR(_("Login is therefore prohibited.")); + WRCRLF; close(fd); } @@ -304,8 +322,8 @@ main(int argc, char *argv[]) /* do syslog message... */ openlog(prog, LOG_CONS, LOG_AUTH); - syslog(LOG_NOTICE, "%s by %s: %s", - opt_reboot ? "rebooted" : "halted", whom, message); + syslog(LOG_NOTICE, _("%s by %s: %s"), + opt_reboot ? _("rebooted") : _("halted"), whom, message); closelog(); if(opt_fast) @@ -335,6 +353,14 @@ main(int argc, char *argv[]) /* turn off accounting */ acct(NULL); #endif + /* RedHat and SuSE like to remove /etc/nologin. + Perhaps the usual sequence is + touch nologin; shutdown -h; fiddle with hardware; + boot; fiddle with software; rm nologin + and removing it here will be counterproductive. + Let us see whether people complain. */ + unlink(_PATH_NOLOGIN); + sync(); sleep(2); @@ -348,9 +374,9 @@ main(int argc, char *argv[]) if(opt_reboot) { my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ - my_puts("\nWhy am I still alive after reboot?"); + my_puts(_("\nWhy am I still alive after reboot?")); } else { - my_puts("\nNow you can turn off the power..."); + my_puts(_("\nNow you can turn off the power...")); /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */ my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ @@ -365,10 +391,10 @@ main(int argc, char *argv[]) void do_halt(char *action) { if (strcasecmp (action, "power_off") == 0) { - printf("Calling kernel power-off facility...\n"); + printf(_("Calling kernel power-off facility...\n")); fflush(stdout); my_reboot(LINUX_REBOOT_CMD_POWER_OFF); - printf("Error powering off\t%s\n", ERRSTRING); + printf(_("Error powering off\t%s\n"), ERRSTRING); fflush(stdout); sleep (2); } else @@ -376,10 +402,10 @@ do_halt(char *action) { /* 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); + printf(_("Executing the program \"%s\" ...\n"), action); fflush(stdout); execl(action, action, NULL); - printf("Error executing\t%s\n", ERRSTRING); + printf(_("Error executing\t%s\n"), ERRSTRING); fflush(stdout); sleep (2); } @@ -402,23 +428,27 @@ write_user(struct utmp *ut) if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0) return; - sprintf(msg, "\007\r\nURGENT: broadcast message from %s:\r\n", whom); + sprintf(msg, _("\007URGENT: broadcast message from %s:"), whom); + WRCRLF; WR(msg); + WRCRLF; if(minutes == 0) { - sprintf(msg, "System going down IMMEDIATELY!\r\n\n"); + sprintf(msg, _("System going down IMMEDIATELY!\n")); } else if(minutes > 60) { hours = minutes / 60; - sprintf(msg, "System going down in %d hour%s %d minutes\r\n", - hours, hours == 1 ? "" : "s", minutes - 60*hours); + sprintf(msg, _("System going down in %d hour%s %d minutes"), + hours, hours == 1 ? "" : _("s"), minutes - 60*hours); } else { - sprintf(msg, "System going down in %d minute%s\r\n\n", - minutes, minutes == 1 ? "" : "s"); + sprintf(msg, _("System going down in %d minute%s\n"), + minutes, minutes == 1 ? "" : _("s")); } WR(msg); + WRCRLF; - sprintf(msg, "\t... %s ...\r\n\n", message); + sprintf(msg, _("\t... %s ...\n"), message); WR(msg); + WRCRLF; close(fd); } @@ -473,7 +503,7 @@ swap_off() sync(); if ((pid = fork()) < 0) { - my_puts("Cannot fork for swapoff. Shrug!"); + my_puts(_("Cannot fork for swapoff. Shrug!")); return; } if (!pid) { @@ -481,8 +511,8 @@ swap_off() execl("/etc/swapoff", SWAPOFF_ARGS, NULL); execl("/bin/swapoff", SWAPOFF_ARGS, NULL); execlp("swapoff", SWAPOFF_ARGS, NULL); - my_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) @@ -500,20 +530,25 @@ unmount_disks() sync(); if ((pid = fork()) < 0) { - my_puts("Cannot fork for umount, trying manually."); + my_puts(_("Cannot fork for umount, trying manually.")); unmount_disks_ourselves(); return; } if (!pid) { execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL); - my_puts("Cannot exec " _PATH_UMOUNT ", trying umount."); + + /* need my_printf instead of my_puts here */ + freopen(_PATH_CONSOLE, "w", stdout); + printf(_("Cannot exec %s, trying umount.\n"), _PATH_UMOUNT); + fflush(stdout); + execlp("umount", UMOUNT_ARGS, NULL); - my_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) ; - my_puts("Unmounting any remaining filesystems..."); + my_puts(_("Unmounting any remaining filesystems...")); unmount_disks_ourselves(); } @@ -549,7 +584,7 @@ unmount_disks_ourselves() printf("umount %s\n", filesys); #else if (umount(mntlist[i]) < 0) - printf("shutdown: Couldn't umount %s\n", filesys); + printf(_("shutdown: Couldn't umount %s\n"), filesys); #endif } } diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c index 1664404c..1e496ad5 100644 --- a/login-utils/simpleinit.c +++ b/login-utils/simpleinit.c @@ -1,6 +1,10 @@ /* simpleinit.c - poe@daimi.aau.dk */ /* Version 1.21 */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + #include #include #include @@ -21,6 +25,7 @@ #include "my_crypt.h" #include "pathnames.h" #include "linux_reboot.h" +#include "nls.h" #define CMDSIZ 150 /* max size of a line in inittab */ #define NUMCMD 30 /* max number of lines in inittab */ @@ -71,15 +76,15 @@ enter_single() pid_t pid; int i; - err("Booting to single user mode.\n"); + err(_("Booting to single user mode.\n")); if((pid = fork()) == 0) { /* the child */ execl(_PATH_BSHELL, _PATH_BSHELL, NULL); - err("exec of single user shell failed\n"); + err(_("exec of single user shell failed\n")); } else if(pid > 0) { while(wait(&i) != pid) /* nothing */; } else if(pid < 0) { - err("fork of single user shell failed\n"); + err(_("fork of single user shell failed\n")); } unlink(_PATH_SINGLE); } @@ -95,6 +100,11 @@ int main(int argc, char *argv[]) signal(SIGTSTP, tstp_handler); signal(SIGINT, int_handler); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* * start up in single user mode if /etc/singleboot exists or if * argv[1] is "single". @@ -206,14 +216,14 @@ int boot_single(int singlearg, int argc, char *argv[]) return 1; /* a bad /etc/passwd should not lock out */ for(i = 0; i < MAXTRIES; i++) { - pass = getpass("Password: "); + pass = getpass(_("Password: ")); if(pass == NULL) continue; if(!strcmp(crypt(pass, rootpass), rootpass)) { return 1; } - puts("\nWrong password.\n"); + puts(_("\nWrong password.\n")); } } else return 1; } @@ -239,16 +249,16 @@ int do_rc() close(0); if(open(_PATH_RC, O_RDONLY, 0) == 0) { execv(_PATH_BSHELL, argv); - err("exec rc failed\n"); + err(_("exec rc failed\n")); _exit(2); } - err("open of rc file failed\n"); + err(_("open of rc file failed\n")); _exit(1); } else if(pid > 0) { /* parent, wait till rc process dies before spawning */ while(wait(&stat) != pid) /* nothing */; } else if(pid < 0) { - err("fork of rc shell failed\n"); + err(_("fork of rc shell failed\n")); } return WEXITSTATUS(stat); } @@ -260,7 +270,7 @@ void spawn(int i) if((pid = fork()) < 0) { inittab[i].pid = -1; - err("fork failed\n"); + err(_("fork failed\n")); return; } if(pid) { @@ -289,7 +299,7 @@ void spawn(int i) env[2] = (char *)0; execve(inittab[i].toks[0], inittab[i].toks, env); - err("exec failed\n"); + err(_("exec failed\n")); sleep(5); _exit(1); } @@ -311,7 +321,7 @@ void read_inittab() /* termenv = "vt100"; */ if(!(f = fopen(_PATH_INITTAB, "r"))) { - err("cannot open inittab\n"); + err(_("cannot open inittab\n")); _exit(1); } @@ -349,7 +359,7 @@ void read_inittab() /* special-case termcap for the console ttys */ (void) sprintf(tty, "/dev/%s", inittab[i].tty); if(!termenv || stat(tty, &stb) < 0) { - err("no TERM or cannot stat tty\n"); + err(_("no TERM or cannot stat tty\n")); } else { /* is it a console tty? */ if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) { diff --git a/login-utils/ttymsg.c b/login-utils/ttymsg.c index 7caf35be..6bf2f82f 100644 --- a/login-utils/ttymsg.c +++ b/login-utils/ttymsg.c @@ -34,6 +34,12 @@ * */ + /* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * Sun Mar 21 1999 - Arnaldo Carvalho de Melo + * - fixed strerr(errno) in gettext calls + */ + #include #include #include @@ -45,6 +51,7 @@ #include #include #include +#include "nls.h" #ifdef __linux__ #include "pathnames.h" @@ -68,19 +75,20 @@ ttymsg(iov, iovcnt, line, tmout) static char errbuf[MAXNAMLEN+1024]; register int cnt, fd, left, wret; struct iovec localiov[6]; - int forked = 0; + int forked = 0, errsv; if (iovcnt > sizeof(localiov) / sizeof(localiov[0])) - return ("too many iov's (change code in wall/ttymsg.c)"); + return (_("too many iov's (change code in wall/ttymsg.c)")); + + /* The old code here rejected the line argument when it contained a '/', + saying: "A slash may be an attempt to break security...". + However, if a user can control the line argument here + then he can make this routine write to /dev/hda or /dev/sda + already. So, this test was worthless, and these days it is + also wrong since people use /dev/pts/xxx. */ - if (strchr(line, '/')) { - /* A slash is an attempt to break security... */ - (void) sprintf(errbuf, "'/' in \"%s\"", device); - errbuf[1024] = 0; /* protect caller */ - return (errbuf); - } if (strlen(line) + sizeof(_PATH_DEV) + 1 > sizeof(device)) { - (void) sprintf(errbuf, "excessively long line arg"); + (void) sprintf(errbuf, _("excessively long line arg")); return (errbuf); } (void) sprintf(device, "%s%s", _PATH_DEV, line); @@ -134,10 +142,12 @@ ttymsg(iov, iovcnt, line, tmout) cpid = fork(); if (cpid < 0) { if (strlen(strerror(errno)) > 1000) - (void) sprintf(errbuf, "cannot fork"); - else + (void) sprintf(errbuf, _("cannot fork")); + else { + errsv = errno; (void) sprintf(errbuf, - "fork: %s", strerror(errno)); + _("fork: %s"), strerror(errsv)); + } (void) close(fd); return (errbuf); } @@ -164,10 +174,12 @@ ttymsg(iov, iovcnt, line, tmout) if (forked) _exit(1); if (strlen(strerror(errno)) > 1000) - (void) sprintf(errbuf, "%s: BAD ERROR", device); - else + (void) sprintf(errbuf, _("%s: BAD ERROR"), device); + else { + errsv = errno; (void) sprintf(errbuf, "%s: %s", device, - strerror(errno)); + strerror(errsv)); + } errbuf[1024] = 0; return (errbuf); } diff --git a/login-utils/vipw.c b/login-utils/vipw.c index 50270a6e..dfcdca2e 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -37,6 +37,11 @@ * . Support for vigr. * * Martin Schulze's patches adapted to Util-Linux by Nicolai Langfeldt. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * Sun Mar 21 1999 - Arnaldo Carvalho de Melo + * - fixed strerr(errno) in gettext calls */ static char version_string[] = "vipw 1.4"; @@ -59,6 +64,7 @@ static char version_string[] = "vipw 1.4"; #include #include "setpwnam.h" +#include "nls.h" #define FILENAMELEN 67 @@ -140,7 +146,7 @@ pw_lock() #if 0 /* flock()ing is superfluous here, with the ptmp/ptmptmp system. */ if (flock(lockfd, LOCK_EX|LOCK_NB)) { (void)fprintf(stderr, - "%s: the %s file is busy.\n", progname, + _("%s: the %s file is busy.\n"), progname, program == VIPW ? "password" : "group" ); exit(1); } @@ -156,13 +162,15 @@ pw_lock() if (ret == -1) { if (errno == EEXIST) (void)fprintf(stderr, - "%s: the %s file is busy (%s present)\n", + _("%s: the %s file is busy (%s present)\n"), progname, program == VIPW ? "password" : "group", tmp_file); - else - (void)fprintf(stderr, "%s: can't link %s: %s\n", progname, - tmp_file, strerror(errno)); + else { + int errsv = errno; + (void)fprintf(stderr, _("%s: can't link %s: %s\n"), progname, + tmp_file, strerror(errsv)); + } exit(1); } copyfile(lockfd, fd); @@ -180,9 +188,10 @@ pw_unlock() unlink(tmp); link(orig_file, tmp); if (rename(tmp_file, orig_file) == -1) { + int errsv = errno; (void)fprintf(stderr, - "%s: can't unlock %s: %s (your changes are still in %s)\n", - progname, orig_file, strerror(errno), tmp_file); + _("%s: can't unlock %s: %s (your changes are still in %s)\n"), + progname, orig_file, strerror(errsv), tmp_file); exit(1); } (void)unlink(tmp_file); @@ -205,7 +214,7 @@ pw_edit(int notsetuid) pid = fork(); if (pid < 0) { - (void)fprintf(stderr, "%s: Cannot fork\n", progname); + (void)fprintf(stderr, _("%s: Cannot fork\n"), progname); exit(1); } if (!pid) { @@ -245,7 +254,7 @@ pw_error(name, err, eval) (void)fprintf(stderr, "%s\n", strerror(sverrno)); } (void)fprintf(stderr, - "%s: %s unchanged\n", progname, orig_file); + _("%s: %s unchanged\n"), progname, orig_file); (void)unlink(tmp_file); exit(eval); } @@ -254,6 +263,10 @@ int main(int argc, char *argv[]) { struct stat begin, end; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + bzero(tmp_file, FILENAMELEN); progname = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0]; if (!strcmp(progname, "vigr")) { @@ -284,7 +297,7 @@ int main(int argc, char *argv[]) if (stat(tmp_file, &end)) pw_error(tmp_file, 1, 1); if (begin.st_mtime == end.st_mtime) { - (void)fprintf(stderr, "%s: no changes made\n", progname); + (void)fprintf(stderr, _("%s: no changes made\n"), progname); pw_error((char *)NULL, 0, 0); } pw_unlock(); diff --git a/login-utils/wall.c b/login-utils/wall.c index eda7e611..70a0df65 100644 --- a/login-utils/wall.c +++ b/login-utils/wall.c @@ -36,6 +36,10 @@ /* * This program is not related to David Wall, whose Stanford Ph.D. thesis * is entitled "Mechanisms for Broadcast and Selective Broadcast". + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -44,12 +48,14 @@ #include #include +#include #include #include #include #include #include #include +#include "nls.h" #ifdef __linux__ #include #include "pathnames.h" @@ -63,6 +69,8 @@ int nobanner; int mbufsize; char *mbuf; +char *progname = "wall"; + /* ARGSUSED */ int main(argc, argv) @@ -72,15 +80,19 @@ main(argc, argv) extern int optind; int ch; struct iovec iov; - struct utmp utmp; - FILE *fp; + struct utmp *utmpptr; char *p, *ttymsg(); - char line[sizeof(utmp.ut_line) + 1]; + char line[sizeof(utmpptr->ut_line) + 1]; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = argv[0]; + p = rindex(progname, '/'); + if (p) + progname = p+1; -#ifdef __linux__ - setlocale(LC_CTYPE,""); -#endif - while ((ch = getopt(argc, argv, "n")) != EOF) switch (ch) { case 'n': @@ -91,7 +103,7 @@ main(argc, argv) case '?': default: usage: - (void)fprintf(stderr, "usage: wall [file]\n"); + (void)fprintf(stderr, _("usage: %s [file]\n"), progname); exit(1); } argc -= optind; @@ -101,26 +113,24 @@ usage: makemsg(*argv); - if (!(fp = fopen(_PATH_UTMP, "r"))) { - (void)fprintf(stderr, "wall: cannot read %s.\n", _PATH_UTMP); - exit(1); - } + setutent(); + iov.iov_base = mbuf; iov.iov_len = mbufsize; - /* NOSTRICT */ - while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) { - if (!utmp.ut_name[0] || - !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) + while((utmpptr = getutent())) { + if (!utmpptr->ut_name[0] || + !strncmp(utmpptr->ut_name, IGNOREUSER, sizeof(utmpptr->ut_name))) + continue; +#ifdef USER_PROCESS + if (utmpptr->ut_type != USER_PROCESS) continue; -#ifdef __linux__ - if (utmp.ut_type != USER_PROCESS) - continue; #endif - strncpy(line, utmp.ut_line, sizeof(utmp.ut_line)); - line[sizeof(utmp.ut_line)-1] = '\0'; + strncpy(line, utmpptr->ut_line, sizeof(utmpptr->ut_line)); + line[sizeof(utmpptr->ut_line)-1] = '\0'; if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) - (void)fprintf(stderr, "wall: %s\n", p); + (void)fprintf(stderr, "%s: %s\n", progname, p); } + endutent(); exit(0); } @@ -138,17 +148,16 @@ makemsg(fname) char *p, *whom, *where, hostname[MAXHOSTNAMELEN], lbuf[MAXHOSTNAMELEN + 320], tmpname[sizeof(_PATH_TMP) + 20]; - char *getlogin(), *strcpy(), *ttyname(); (void)sprintf(tmpname, "%s/wall.XXXXXX", _PATH_TMP); if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) { - (void)fprintf(stderr, "wall: can't open temporary file.\n"); + (void)fprintf(stderr, _("%s: can't open temporary file.\n"), progname); exit(1); } (void)unlink(tmpname); if (!nobanner) { - if (!(whom = getlogin())) + if (!(whom = getlogin()) || !*whom) whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; if (!whom || strlen(whom) > 100) whom = "someone"; @@ -169,7 +178,7 @@ makemsg(fname) /* snprintf is not always available, but the sprintf's here will not overflow as long as %d takes at most 100 chars */ (void)fprintf(fp, "\r%79s\r\n", " "); - (void)sprintf(lbuf, "Broadcast Message from %s@%s", + (void)sprintf(lbuf, _("Broadcast Message from %s@%s"), whom, hostname); (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); (void)sprintf(lbuf, " (%s) at %d:%02d ...", @@ -179,7 +188,7 @@ makemsg(fname) (void)fprintf(fp, "%79s\r\n", " "); if (fname && !(freopen(fname, "r", stdin))) { - (void)fprintf(stderr, "wall: can't read %s.\n", fname); + (void)fprintf(stderr, _("%s: can't read %s.\n"), progname, fname); exit(1); } while (fgets(lbuf, sizeof(lbuf), stdin)) @@ -204,16 +213,16 @@ makemsg(fname) rewind(fp); if (fstat(fd, &sbuf)) { - (void)fprintf(stderr, "wall: can't stat temporary file.\n"); + (void)fprintf(stderr, _("%s: can't stat temporary file.\n"), progname); exit(1); } mbufsize = sbuf.st_size; if (!(mbuf = malloc((u_int)mbufsize))) { - (void)fprintf(stderr, "wall: out of memory.\n"); + (void)fprintf(stderr, _("%s: Out of memory!\n"), progname); exit(1); } if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) { - (void)fprintf(stderr, "wall: can't read temporary file.\n"); + (void)fprintf(stderr, _("%s: can't read temporary file.\n"), progname); exit(1); } (void)close(fd); diff --git a/misc-utils/Makefile b/misc-utils/Makefile index 9ccf489b..eeaf5676 100644 --- a/misc-utils/Makefile +++ b/misc-utils/Makefile @@ -4,14 +4,14 @@ # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) # May be distirbuted under the GPL # - +include ../make_include include ../MCONFIG # Where to put man pages? MAN1= cal.1 chkdupexe.1 ddate.1 kill.1 \ logger.1 look.1 mcookie.1 namei.1 script.1 \ - setterm.1 tsort.1 whereis.1 write.1 + tsort.1 whereis.1 write.1 # Where to put binaries? # See the "install" rule for the links. . . @@ -19,7 +19,7 @@ MAN1= cal.1 chkdupexe.1 ddate.1 kill.1 \ BIN= kill USRBIN= cal chkdupexe ddate logger look mcookie \ - namei script setterm tsort whereis write + namei script tsort whereis write ifeq "$(HAVE_CLEAR)" "no" USRBIN:=$(USRBIN) clear @@ -31,14 +31,21 @@ USRBIN:=$(USRBIN) reset MAN1:=$(MAN1) reset.1 endif +ifeq "$(HAVE_NCURSES)" "yes" +USRBIN:=$(USRBIN) setterm +MAN1:=$(MAN1) setterm.1 +endif + # For script only +LIBPTY= ifeq "$(HAVE_OPENPTY)" "yes" -CFLAGS:=$(CFLAGS) -DHAVE_OPENPTY +LIBPTY:=$(LIBPTY) -lutil endif # Programs requiring special compilation NEEDS_CURSES= setterm +NEEDS_OPENPTY= script all: $(BIN) $(USRBIN) $(USRBIN.NONSHADOW) $(USRGAMES) @@ -49,6 +56,9 @@ else @echo $@ not made since it requires ncurses endif +$(NEEDS_OPENPTY): + $(CC) $(LDFLAGS) $^ -o $@ $(LIBPTY) + %: %.sh cp $@.sh $@ chmod 755 $@ @@ -68,12 +78,12 @@ mcookie: mcookie.o md5.o mcookie.o: mcookie.c md5.h md5.o: md5.c md5.h reset: reset.sh +script: script.o ifeq "$(HAVE_NCURSES)" "yes" setterm: setterm.o endif - install: all $(INSTALLDIR) $(BINDIR) $(USRBINDIR) $(INSTALLBIN) $(BIN) $(BINDIR) diff --git a/misc-utils/cal.c b/misc-utils/cal.c index ab642014..e3acf74b 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -36,15 +36,11 @@ /* 1999-02-01 Jean-Francois Bignolles: added option '-m' to display * monday as the first day of the week. + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ -/* 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? - Dunno. */ - -#include "/usr/include/_G_config.h" - #include #include @@ -55,19 +51,13 @@ #include #include #include +#include "nls.h" +#include "../defines.h" -/* Test changes to deal with gnulibc, Linux libc 5. */ -/* #if defined(__linux__) && _LINUX_C_LIB_VERSION_MAJOR > 4 */ -#if _LINUX_C_LIB_VERSION_MAJOR - 0 > 4 || __GNU_LIBRARY__ - 0 >= 5 -# define LANGINFO 1 -#else -# define LANGINFO 0 -#endif - -#if LANGINFO +#ifdef HAVE_langinfo_h # include #else -# include +# include /* libc4 only */ #endif #define THURSDAY 4 /* for reformation */ @@ -162,7 +152,11 @@ main(argc, argv) extern char *__progname; __progname = argv[0]; #endif - + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + setlocale(LC_ALL,""); yflag = 0; while ((ch = getopt(argc, argv, "mjy")) != EOF) @@ -187,11 +181,11 @@ main(argc, argv) switch(argc) { case 2: if ((month = atoi(*argv++)) < 1 || month > 12) - errx(1, "illegal month value: use 1-12"); + errx(1, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: if ((year = atoi(*argv)) < 1 || year > 9999) - errx(1, "illegal year value: use 1-9999"); + errx(1, _("illegal year value: use 1-9999")); break; case 0: (void)time(&now); @@ -228,7 +222,7 @@ void headers_init(void) strcpy(day_headings,""); strcpy(j_day_headings,""); -#if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1) +#ifdef HAVE_langinfo_h # define weekday(wd) nl_langinfo(ABDAY_1+wd) #else # define weekday(wd) _time_info->abbrev_wkday[wd] @@ -247,7 +241,7 @@ void headers_init(void) #undef weekday for (i = 0; i < 12; i++) { -#if defined(__linux__) && (_LINUX_C_LIB_VERSION_MAJOR > 4 || __GNU_LIBRARY__ > 1) +#ifdef HAVE_langinfo_h full_month[i] = nl_langinfo(MON_1+i); #else full_month[i] = _time_info->full_month[i]; @@ -487,6 +481,6 @@ void usage() { - (void)fprintf(stderr, "usage: cal [-mjy] [[month] year]\n"); + (void)fprintf(stderr, _("usage: cal [-mjy] [[month] year]\n")); exit(1); } diff --git a/misc-utils/ddate.c b/misc-utils/ddate.c index 09704e0b..7f12e86f 100644 --- a/misc-utils/ddate.c +++ b/misc-utils/ddate.c @@ -26,6 +26,9 @@ 59 Bcy, 3161: PRAISE_BOB and KILL_BOB options split, other minor changes. + 1999-02-22 Arkadiusz Mi¶kiewicz + - added Native Language Support + */ @@ -57,6 +60,7 @@ #include #include #include +#include "nls.h" #ifndef __GNUC__ #define inline /* foo */ @@ -147,6 +151,10 @@ main (int argc, char *argv[]) char schwa[23*17], *fnord=0; int pi; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + srandom(time(NULL)); /* do args here */ for(pi=1; pi * may be used / modified / distributed under the same terms as the original. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -42,6 +46,7 @@ #include #include #include +#include "nls.h" #define SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -151,6 +156,10 @@ int main (int argc, char *argv[]) int do_pid, do_kill, check_all; int *pids, *ip; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + whoami = mybasename (*argv); numsig = SIGTERM; do_pid = (! strcmp (whoami, "pid")); @@ -187,7 +196,7 @@ int main (int argc, char *argv[]) /* argc == 2 */ arg = argv[1]; if ((numsig = arg_to_signum (arg)) < 0) { - fprintf (stderr, "%s: unknown signal %s\n", whoami, arg); + fprintf (stderr, _("%s: unknown signal %s\n"), whoami, arg); return 1; } printsig (numsig); @@ -249,7 +258,7 @@ int main (int argc, char *argv[]) pids = get_pids (arg, check_all); if (! pids) { errors++; - fprintf (stderr, "%s: can't find process \"%s\"\n", + fprintf (stderr, _("%s: can't find process \"%s\"\n"), whoami, arg); continue; } @@ -291,7 +300,7 @@ int arg_to_signum (char *arg) void nosig (char *name) { - fprintf (stderr, "%s: unknown signal %s; valid signals:\n", whoami, name); + fprintf (stderr, _("%s: unknown signal %s; valid signals:\n"), whoami, name); printsignals (stderr); } @@ -331,8 +340,8 @@ int usage (int status) FILE *fp; fp = (status == 0 ? stdout : stderr); - fprintf (fp, "usage: %s [ -s signal | -p ] [ -a ] pid ...\n", whoami); - fprintf (fp, " %s -l [ signal ]\n", whoami); + fprintf (fp, _("usage: %s [ -s signal | -p ] [ -a ] pid ...\n"), whoami); + fprintf (fp, _(" %s -l [ signal ]\n"), whoami); return status; } diff --git a/misc-utils/logger.1 b/misc-utils/logger.1 index 0621dba1..82df6be7 100644 --- a/misc-utils/logger.1 +++ b/misc-utils/logger.1 @@ -43,6 +43,7 @@ .Op Fl f Ar file .Op Fl p Ar pri .Op Fl t Ar tag +.Op Fl u Ar socket .Op Ar message ... .Sh DESCRIPTION .Nm Logger @@ -73,6 +74,10 @@ The default is ``user.notice.'' .It Fl t Ar tag Mark every line in the log with the specified .Ar tag . +.It Fl u Ar sock +Write to socket as specified with +.Ar socket +instead of builtin syslog routines. .It Ar message Write the message to log; if not specified, and the .Fl f diff --git a/misc-utils/logger.c b/misc-utils/logger.c index e59fe12b..4c881c96 100644 --- a/misc-utils/logger.c +++ b/misc-utils/logger.c @@ -29,14 +29,23 @@ * 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. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * Sun Mar 21 1999 - Arnaldo Carvalho de Melo + * - fixed strerr(errno) in gettext calls */ #include #include #include +#include #include #include #include +#include +#include +#include "nls.h" #define SYSLOG_NAMES #include @@ -45,6 +54,65 @@ int decode __P((char *, CODE *)); int pencode __P((char *)); void usage __P((void)); +int +myopenlog(sock) + const char *sock; +{ + int fd; + static struct sockaddr s_addr; /* AF_UNIX address of local logger */ + + s_addr.sa_family = AF_UNIX; + (void)strncpy(s_addr.sa_data, sock, sizeof(s_addr.sa_data)); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + printf ("socket: %s.\n", strerror(errno)); + exit (1); + } + + if (connect(fd, &s_addr, sizeof(s_addr.sa_family)+strlen(s_addr.sa_data)) == -1) { + printf ("connect: %s.\n", strerror(errno)); + exit (1); + } + return fd; +} + +void +mysyslog(fd, logflags, pri, tag, msg) + int fd; + int logflags; + int pri; + char *tag; + char *msg; +{ + char buf[1000], pid[30], *cp, *tp; + time_t now; + + if (fd > -1) { + /* there was a gethostname call here, but its output was not used */ + /* avoid snprintf - it does not exist on ancient systems */ + if (logflags & LOG_PID) + sprintf (pid, "[%d]", getpid()); + else + pid[0] = 0; + if (tag) + cp = tag; + else { + cp = getlogin(); + if (!cp) + cp = ""; + } + (void)time(&now); + tp = ctime(&now)+4; + + /* do snprintf by hand - ugly, but for once... */ + sprintf(buf, "<%d>%.15s %.200s%s: %.400s", + pri, tp, cp, pid, msg); + + if (write(fd, buf, strlen(buf)+1) < 0) + return; /* error */ + } +} + /* * logger -- read and log utility * @@ -58,16 +126,23 @@ main(argc, argv) { int ch, logflags, pri; char *tag, buf[1024]; + char *usock = NULL; + int LogSock = -1; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); tag = NULL; pri = LOG_NOTICE; logflags = 0; - while ((ch = getopt(argc, argv, "f:ip:st:")) != EOF) + while ((ch = getopt(argc, argv, "f:ip:st:u:")) != EOF) switch((char)ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) { - (void)fprintf(stderr, "logger: %s: %s.\n", - optarg, strerror(errno)); + int errsv = errno; + (void)fprintf(stderr, _("logger: %s: %s.\n"), + optarg, strerror(errsv)); exit(1); } break; @@ -83,6 +158,9 @@ main(argc, argv) case 't': /* tag */ tag = optarg; break; + case 'u': /* unix socket */ + usock = optarg; + break; case '?': default: usage(); @@ -91,7 +169,11 @@ main(argc, argv) argv += optind; /* setup for logging */ - openlog(tag ? tag : getlogin(), logflags, 0); + if (!usock) + openlog(tag ? tag : getlogin(), logflags, 0); + else + LogSock = myopenlog(usock); + (void) fclose(stdout); /* log input line if appropriate */ @@ -102,23 +184,41 @@ main(argc, argv) for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { len = strlen(*argv); if (p + len > endp && p > buf) { + if (!usock) syslog(pri, "%s", buf); + else + mysyslog(LogSock, logflags, pri, tag, buf); p = buf; } - if (len > sizeof(buf) - 1) + if (len > sizeof(buf) - 1) { + if (!usock) syslog(pri, "%s", *argv++); - else { + else + mysyslog(LogSock, logflags, pri, tag, *argv++); + } else { if (p != buf) *p++ = ' '; bcopy(*argv++, p, len); *(p += len) = '\0'; } } - if (p != buf) + if (p != buf) { + if (!usock) syslog(pri, "%s", buf); + else + mysyslog(LogSock, logflags, pri, tag, buf); + } } else - while (fgets(buf, sizeof(buf), stdin) != NULL) + while (fgets(buf, sizeof(buf), stdin) != NULL) { + if (!usock) syslog(pri, "%s", buf); + else + mysyslog(LogSock, logflags, pri, tag, buf); + } + if (!usock) + closelog(); + else + close(LogSock); exit(0); } @@ -138,19 +238,19 @@ pencode(s) fac = decode(save, facilitynames); if (fac < 0) { (void)fprintf(stderr, - "logger: unknown facility name: %s.\n", save); + _("logger: unknown facility name: %s.\n"), save); exit(1); } *s++ = '.'; } else { - fac = 0; + fac = LOG_USER; s = save; } lev = decode(s, prioritynames); if (lev < 0) { (void)fprintf(stderr, - "logger: unknown priority name: %s.\n", save); + _("logger: unknown priority name: %s.\n"), save); exit(1); } return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); @@ -177,6 +277,6 @@ void usage() { (void)fprintf(stderr, - "logger: [-is] [-f file] [-p pri] [-t tag] [ message ... ]\n"); + _("usage: logger [-is] [-f file] [-p pri] [-t tag] [-u socket] [ message ... ]\n")); exit(1); } diff --git a/misc-utils/look.c b/misc-utils/look.c index 72256c19..9e6c15bf 100644 --- a/misc-utils/look.c +++ b/misc-utils/look.c @@ -34,6 +34,10 @@ * SUCH DAMAGE. */ + /* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + /* * look -- find lines in a sorted list. * @@ -56,6 +60,7 @@ #include #include #include "pathnames.h" +#include "nls.h" #define EQUAL 0 #define GREATER 1 @@ -83,6 +88,10 @@ main(int argc, char *argv[]) int ch, fd, termchar; char *back, *file, *front, *p; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + setlocale(LC_ALL, ""); file = _PATH_WORDS; @@ -158,7 +167,7 @@ look(char *front, char *back) comparbuf = malloc(stringlen+1); if (comparbuf == NULL) - err("Out of memory"); + err(_("Out of memory")); front = binary_search(front, back); front = linear_search(front, back); @@ -328,7 +337,7 @@ compare(char *s2, char *s2end, int nocase) { static void usage() { - (void)fprintf(stderr, "usage: look [-dfa] [-t char] string [file]\n"); + (void)fprintf(stderr, _("usage: look [-dfa] [-t char] string [file]\n")); exit(2); } diff --git a/misc-utils/mcookie.c b/misc-utils/mcookie.c index 33ae7630..9f13b49d 100644 --- a/misc-utils/mcookie.c +++ b/misc-utils/mcookie.c @@ -1,7 +1,7 @@ /* mcookie.c -- Generates random numbers for xauth * Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu - * Revised: Mon Sep 25 23:44:43 1995 by r.faith@ieee.org - * Public Domain 1995 Rickard E. Faith (faith@cs.unc.edu) + * Revised: Fri Mar 19 07:48:01 1999 by faith@acm.org + * Public Domain 1995, 1999 Rickard E. Faith (faith@acm.org) * This program comes with ABSOLUTELY NO WARRANTY. * * $Id: mcookie.c,v 1.5 1997/07/06 00:13:06 aebr Exp $ @@ -13,6 +13,11 @@ * NOTE: Unless /dev/random is available, this program does not actually * gather 128 bits of random information, so the magic cookie generated * will be considerably easier to guess than one might expect. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * 1999-03-21 aeb: Added some fragments of code from Colin Plumb. + * */ #ifdef __linux__ @@ -27,29 +32,48 @@ #include #include #endif +#include "nls.h" -#define MAXBUFFERSIZE 512 +#define BUFFERSIZE 4096 struct rngs { const char *path; - int length; + int minlength, maxlength; } rngs[] = { - { "/dev/random", 16 }, - { "/dev/urandom", 128 }, - { "/proc/stat", MAXBUFFERSIZE }, - { "/proc/loadavg", MAXBUFFERSIZE }, - { "/dev/audio", MAXBUFFERSIZE }, + { "/dev/random", 16, 16 }, /* 16 bytes = 128 bits suffice */ + { "/proc/interrupts", 0, 0 }, + { "/proc/slabinfo", 0, 0 }, + { "/proc/stat", 0, 0 }, + { "/dev/urandom", 32, 64 }, }; #define RNGS (sizeof(rngs)/sizeof(struct rngs)) int Verbose = 0; +/* The basic function to hash a file */ +static off_t +hash_file(struct MD5Context *ctx, int fd) +{ + off_t count = 0; + ssize_t r; + unsigned char buf[BUFFERSIZE]; + + while ((r = read(fd, buf, sizeof(buf))) > 0) { + MD5Update(ctx, buf, r); + count += r; + } + /* Separate files with a null byte */ + buf[0] = 0; + MD5Update(ctx, buf, 1); + return count; +} + int main( int argc, char **argv ) { int i; struct MD5Context ctx; unsigned char digest[16]; - unsigned char buf[MAXBUFFERSIZE]; + unsigned char buf[BUFFERSIZE]; int fd; int c; pid_t pid; @@ -62,6 +86,10 @@ int main( int argc, char **argv ) long int t; #endif + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + while ((c = getopt( argc, argv, "vf:" )) != EOF) switch (c) { case 'v': ++Verbose; break; @@ -85,39 +113,52 @@ int main( int argc, char **argv ) if (file) { int count = 0; - if (file[0] == '-' && !file[1]) fd = fileno(stdin); - else if ((fd = open( file, O_RDONLY )) <0) { - fprintf( stderr, "Could not open %s\n", file ); - } + if (file[0] == '-' && !file[1]) + fd = fileno(stdin); + else + fd = open( file, O_RDONLY ); + + if (fd < 0) { + fprintf( stderr, _("Could not open %s\n"), file ); + } else { + count = hash_file( &ctx, fd ); + if (Verbose) + fprintf( stderr, _("Got %d bytes from %s\n"), count, file ); - while ((r = read( fd, buf, sizeof( buf ) )) > 0) { - MD5Update( &ctx, buf, r ); - count += r; + if (file[0] != '-' || file[1]) close( fd ); } - if (Verbose) - fprintf( stderr, "Got %d bytes from %s\n", count, file ); - - if (file[0] != '-' || file[1]) close( fd ); } for (i = 0; i < RNGS; i++) { if ((fd = open( rngs[i].path, O_RDONLY|O_NONBLOCK )) >= 0) { - r = read( fd, buf, sizeof( buf ) ); + int count = sizeof(buf); + + if (rngs[i].maxlength && count > rngs[i].maxlength) + count = rngs[i].maxlength; + r = read( fd, buf, count ); 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 ); - if (r >= rngs[i].length) break; + fprintf( stderr, _("Got %d bytes from %s\n"), r, rngs[i].path ); + if (rngs[i].minlength && r >= rngs[i].minlength) + break; } else if (Verbose) - fprintf( stderr, "Could not open %s\n", rngs[i].path ); + fprintf( stderr, _("Could not open %s\n"), rngs[i].path ); } MD5Final( digest, &ctx ); for (i = 0; i < 16; i++) printf( "%02x", digest[i] ); putchar ( '\n' ); + /* + * The following is important for cases like disk full, so shell scripts + * can bomb out properly rather than think they succeeded. + */ + if (fflush(stdout) < 0 || fclose(stdout) < 0) + return 1; + return 0; } diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 36a17dfd..f110e638 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -39,6 +39,9 @@ the maximum number of symbolic links this system can have. The program exits with a 1 status ONLY if it finds it cannot chdir to /, or if it encounters an unknown file type. +1999-02-22 Arkadiusz Mi¶kiewicz +- added Native Language Support + -------------------------------------------------------------*/ #include @@ -47,6 +50,7 @@ chdir to /, or if it encounters an unknown file type. #include #include #include +#include "nls.h" #ifndef __GNU_LIBRARY__ extern char *sys_errlist[]; @@ -76,6 +80,10 @@ char *argv[]; register int c; char curdir[MAXPATHLEN]; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + if(argc < 2) usage(); @@ -96,7 +104,7 @@ char *argv[]; } if(getcwd(curdir, sizeof(curdir)) == NULL){ - (void)fprintf(stderr, "namei: unable to get current directory - %s\n", curdir); + (void)fprintf(stderr, _("namei: unable to get current directory - %s\n"), curdir); exit(1); } @@ -107,7 +115,7 @@ char *argv[]; namei(argv[optind], 0); if(chdir(curdir) == -1){ - (void)fprintf(stderr, "namei: unable to chdir to %s - %s (%d)\n", curdir, ERR); + (void)fprintf(stderr, _("namei: unable to chdir to %s - %s (%d)\n"), curdir, ERR); exit(1); } } @@ -117,7 +125,7 @@ char *argv[]; void usage() { - (void)fprintf(stderr,"usage: namei [-mx] pathname [pathname ...]\n"); + (void)fprintf(stderr,_("usage: namei [-mx] pathname [pathname ...]\n")); exit(1); } @@ -146,14 +154,14 @@ register int lev; file++; if(chdir("/") == -1){ - (void)fprintf(stderr,"namei: could not chdir to root!\n"); + (void)fprintf(stderr,_("namei: could not chdir to root!\n")); exit(1); } for(i = 0; i < lev; i++) (void)printf(" "); if(stat("/", &stb) == -1){ - (void)fprintf(stderr, "namei: could not stat root!\n"); + (void)fprintf(stderr, _("namei: could not stat root!\n")); exit(1); } lastdev = stb.st_dev; @@ -208,7 +216,7 @@ register int lev; */ if(chdir(buf) == -1){ - (void)printf(" ? could not chdir into %s - %s (%d)\n", buf, ERR ); + (void)printf(_(" ? could not chdir into %s - %s (%d)\n"), buf, ERR ); return; } if(xflag && lastdev != stb.st_dev && lastdev != NODEV){ @@ -237,7 +245,7 @@ register int lev; bzero(sym, BUFSIZ); if(readlink(buf, sym, BUFSIZ) == -1){ - (void)printf(" ? problems reading symlink %s - %s (%d)\n", buf, ERR); + (void)printf(_(" ? problems reading symlink %s - %s (%d)\n"), buf, ERR); return; } @@ -247,7 +255,7 @@ register int lev; (void)printf(" l %s -> %s", buf, sym); if(symcount > 0 && symcount++ > MAXSYMLINKS){ - (void)printf(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***"); + (void)printf(_(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***")); symcount = -1; } (void)printf("\n"); @@ -283,7 +291,7 @@ register int lev; break; default: - (void)fprintf(stderr,"namei: unknown file type 0%06o on file %s\n", stb.st_mode, buf ); + (void)fprintf(stderr,_("namei: unknown file type 0%06o on file %s\n"), stb.st_mode, buf ); exit(1); } diff --git a/misc-utils/script.c b/misc-utils/script.c index 23c48ea6..283bc8fc 100644 --- a/misc-utils/script.c +++ b/misc-utils/script.c @@ -31,6 +31,10 @@ * SUCH DAMAGE. */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + /* * script */ @@ -43,13 +47,15 @@ #include #include #include +#include "nls.h" #ifdef __linux__ #include #include #endif -#ifdef HAVE_OPENPTY +#include "../defines.h" +#ifdef HAVE_openpty #include #endif @@ -74,7 +80,7 @@ struct termios tt; struct winsize win; int lb; int l; -#ifndef HAVE_OPENPTY +#ifndef HAVE_openpty char line[] = "/dev/ptyXX"; #endif int aflg; @@ -89,6 +95,10 @@ main(argc, argv) void finish(); char *getenv(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + while ((ch = getopt(argc, argv, "a")) != EOF) switch((char)ch) { case 'a': @@ -96,7 +106,7 @@ main(argc, argv) break; case '?': default: - fprintf(stderr, "usage: script [-a] [file]\n"); + fprintf(stderr, _("usage: script [-a] [file]\n")); exit(1); } argc -= optind; @@ -116,7 +126,7 @@ main(argc, argv) shell = _PATH_BSHELL; getmaster(); - printf("Script started, file is %s\n", fname); + printf(_("Script started, file is %s\n"), fname); fixtty(); (void) signal(SIGCHLD, finish); @@ -148,7 +158,7 @@ doinput() char ibuf[BUFSIZ]; (void) fclose(fscript); -#ifdef HAVE_OPENPTY +#ifdef HAVE_openpty (void) close(slave); #endif while ((cc = read(0, ibuf, BUFSIZ)) > 0) @@ -181,11 +191,11 @@ dooutput() char obuf[BUFSIZ], *ctime(); (void) close(0); -#ifdef HAVE_OPENPTY +#ifdef HAVE_openpty (void) close(slave); #endif tvec = time((time_t *)NULL); - fprintf(fscript, "Script started on %s", ctime(&tvec)); + fprintf(fscript, _("Script started on %s"), ctime(&tvec)); for (;;) { cc = read(master, obuf, sizeof (obuf)); if (cc <= 0) @@ -251,12 +261,12 @@ done() if (subchild) { tvec = time((time_t *)NULL); - fprintf(fscript,"\nScript done on %s", ctime(&tvec)); + fprintf(fscript,_("\nScript done on %s"), ctime(&tvec)); (void) fclose(fscript); (void) close(master); } else { (void) tcsetattr(0, TCSAFLUSH, &tt); - printf("Script done, file is %s\n", fname); + printf(_("Script done, file is %s\n"), fname); } exit(0); } @@ -264,11 +274,11 @@ done() void getmaster() { -#ifdef HAVE_OPENPTY +#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"); + fprintf(stderr, _("openpty failed\n")); fail(); } #else @@ -302,15 +312,15 @@ getmaster() } } } - fprintf(stderr, "Out of pty's\n"); + fprintf(stderr, _("Out of pty's\n")); fail(); -#endif /* not HAVE_OPENPTY */ +#endif /* not HAVE_openpty */ } void getslave() { -#ifndef HAVE_OPENPTY +#ifndef HAVE_openpty line[strlen("/dev/")] = 't'; slave = open(line, O_RDWR); if (slave < 0) { diff --git a/misc-utils/setterm.c b/misc-utils/setterm.c index 3b3e6c24..b9e4c0da 100644 --- a/misc-utils/setterm.c +++ b/misc-utils/setterm.c @@ -16,6 +16,10 @@ * * Converted to terminfo by Kars de Jong (jongk@cs.utwente.nl) * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * + * * Syntax: * * setterm @@ -106,6 +110,7 @@ #endif #include #include +#include "nls.h" #ifndef TCGETS /* TCGETS is either defined in termios.h, or here: */ @@ -737,58 +742,58 @@ char *prog_name; /* Name of this program. */ { /* Print error message about arguments, and the command's syntax. */ - fprintf(stderr, "%s: Argument error, usage\n", prog_name); + fprintf(stderr, _("%s: Argument error, usage\n"), prog_name); fprintf(stderr, "\n"); fprintf(stderr, "%s\n", prog_name); - fprintf(stderr, " [ -term terminal_name ]\n"); - fprintf(stderr, " [ -reset ]\n"); - fprintf(stderr, " [ -initialize ]\n"); - fprintf(stderr, " [ -cursor [on|off] ]\n"); + fprintf(stderr, _(" [ -term terminal_name ]\n")); + fprintf(stderr, _(" [ -reset ]\n")); + fprintf(stderr, _(" [ -initialize ]\n")); + fprintf(stderr, _(" [ -cursor [on|off] ]\n")); #if 0 - fprintf(stderr, " [ -snow [on|off] ]\n"); - fprintf(stderr, " [ -softscroll [on|off] ]\n"); - fprintf(stderr, " [ -keyboard pc|olivetti|dutch|extended ]\n"); + fprintf(stderr, _(" [ -snow [on|off] ]\n")); + fprintf(stderr, _(" [ -softscroll [on|off] ]\n")); + fprintf(stderr, _(" [ -keyboard pc|olivetti|dutch|extended ]\n")); #endif - fprintf(stderr, " [ -repeat [on|off] ]\n"); - fprintf(stderr, " [ -appcursorkeys [on|off] ]\n"); - fprintf(stderr, " [ -linewrap [on|off] ]\n"); - fprintf(stderr, " [ -default ]\n"); - fprintf(stderr, " [ -foreground black|blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white|default ]\n"); - fprintf(stderr, " [ -background black|blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white|default ]\n"); - fprintf(stderr, " [ -ulcolor black|grey|blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white ]\n"); - fprintf(stderr, " [ -ulcolor bright blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white ]\n"); - fprintf(stderr, " [ -hbcolor black|grey|blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white ]\n"); - fprintf(stderr, " [ -hbcolor bright blue|green|cyan"); - fprintf(stderr, "|red|magenta|yellow|white ]\n"); + fprintf(stderr, _(" [ -repeat [on|off] ]\n")); + fprintf(stderr, _(" [ -appcursorkeys [on|off] ]\n")); + fprintf(stderr, _(" [ -linewrap [on|off] ]\n")); + fprintf(stderr, _(" [ -default ]\n")); + fprintf(stderr, _(" [ -foreground black|blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white|default ]\n")); + fprintf(stderr, _(" [ -background black|blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white|default ]\n")); + fprintf(stderr, _(" [ -ulcolor black|grey|blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white ]\n")); + fprintf(stderr, _(" [ -ulcolor bright blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white ]\n")); + fprintf(stderr, _(" [ -hbcolor black|grey|blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white ]\n")); + fprintf(stderr, _(" [ -hbcolor bright blue|green|cyan")); + fprintf(stderr, _("|red|magenta|yellow|white ]\n")); #if 0 - fprintf(stderr, " [ -standout [ attr ] ]\n"); + fprintf(stderr, _(" [ -standout [ attr ] ]\n")); #endif - fprintf(stderr, " [ -inversescreen [on|off] ]\n"); - fprintf(stderr, " [ -bold [on|off] ]\n"); - fprintf(stderr, " [ -half-bright [on|off] ]\n"); - fprintf(stderr, " [ -blink [on|off] ]\n"); - fprintf(stderr, " [ -reverse [on|off] ]\n"); - fprintf(stderr, " [ -underline [on|off] ]\n"); - fprintf(stderr, " [ -store ]\n"); - fprintf(stderr, " [ -clear [all|rest] ]\n"); - fprintf(stderr, " [ -tabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n"); - fprintf(stderr, " [ -clrtabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n"); - fprintf(stderr, " [ -regtabs [1-160] ]\n"); - fprintf(stderr, " [ -blank [0-60] ]\n"); - fprintf(stderr, " [ -dump [1-NR_CONSOLES] ]\n"); - fprintf(stderr, " [ -append [1-NR_CONSOLES] ]\n"); - fprintf(stderr, " [ -file dumpfilename ]\n"); - fprintf(stderr, " [ -msg [on|off] ]\n"); - fprintf(stderr, " [ -msglevel [0-8] ]\n"); - fprintf(stderr, " [ -powersave [on|vsync|hsync|powerdown|off] ]\n"); - fprintf(stderr, " [ -powerdown [0-60] ]\n"); - fprintf(stderr, " [ -blength [0-2000] ]\n"); - fprintf(stderr, " [ -bfreq freqnumber ]\n"); + fprintf(stderr, _(" [ -inversescreen [on|off] ]\n")); + fprintf(stderr, _(" [ -bold [on|off] ]\n")); + fprintf(stderr, _(" [ -half-bright [on|off] ]\n")); + fprintf(stderr, _(" [ -blink [on|off] ]\n")); + fprintf(stderr, _(" [ -reverse [on|off] ]\n")); + fprintf(stderr, _(" [ -underline [on|off] ]\n")); + fprintf(stderr, _(" [ -store ]\n")); + fprintf(stderr, _(" [ -clear [all|rest] ]\n")); + fprintf(stderr, _(" [ -tabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n")); + fprintf(stderr, _(" [ -clrtabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n")); + fprintf(stderr, _(" [ -regtabs [1-160] ]\n")); + fprintf(stderr, _(" [ -blank [0-60] ]\n")); + fprintf(stderr, _(" [ -dump [1-NR_CONSOLES] ]\n")); + fprintf(stderr, _(" [ -append [1-NR_CONSOLES] ]\n")); + fprintf(stderr, _(" [ -file dumpfilename ]\n")); + fprintf(stderr, _(" [ -msg [on|off] ]\n")); + fprintf(stderr, _(" [ -msglevel [0-8] ]\n")); + fprintf(stderr, _(" [ -powersave [on|vsync|hsync|powerdown|off] ]\n")); + fprintf(stderr, _(" [ -powerdown [0-60] ]\n")); + fprintf(stderr, _(" [ -blength [0-2000] ]\n")); + fprintf(stderr, _(" [ -bfreq freqnumber ]\n")); } char *ti_entry(name) @@ -833,16 +838,16 @@ int vcterm; /* Set if terminal is a virtual console. */ if (opt_keyboard && vcterm) { switch (opt_ke_type) { case PC: - printf("%s%s%s", DCS, "keyboard.pc", ST); + printf("%s%s%s", DCS, _("keyboard.pc"), ST); break; case OLIVETTI: - printf("%s%s%s", DCS, "keyboard.olivetti", ST); + printf("%s%s%s", DCS, _("keyboard.olivetti"), ST); break; case DUTCH: - printf("%s%s%s", DCS, "keyboard.dutch", ST); + printf("%s%s%s", DCS, _("keyboard.dutch"), ST); break; case EXTENDED: - printf("%s%s%s", DCS, "keyboard.extended", ST); + printf("%s%s%s", DCS, _("keyboard.extended"), ST); break; } } @@ -876,17 +881,17 @@ int vcterm; /* Set if terminal is a virtual console. */ /* -snow [on|off]. Vc only. */ if (opt_snow && vcterm) { if (opt_sn_on) - printf("%s%s%s", DCS, "snow.on", ST); + printf("%s%s%s", DCS, _("snow.on"), ST); else - printf("%s%s%s", DCS, "snow.off", ST); + printf("%s%s%s", DCS, _("snow.off"), ST); } /* -softscroll [on|off]. Vc only. */ if (opt_softscroll && vcterm) { if (opt_so_on) - printf("%s%s%s", DCS, "softscroll.on", ST); + printf("%s%s%s", DCS, _("softscroll.on"), ST); else - printf("%s%s%s", DCS, "softscroll.off", ST); + printf("%s%s%s", DCS, _("softscroll.off"), ST); } #endif @@ -1061,7 +1066,7 @@ int vcterm; /* Set if terminal is a virtual console. */ ioctlarg[0] = 10; /* powersave */ ioctlarg[1] = opt_ps_mode; if (ioctl(0,TIOCLINUX,ioctlarg)) - fprintf(stderr,"cannot (un)set powersave mode\n"); + fprintf(stderr,_("cannot (un)set powersave mode\n")); } /* -powerdown [0-60]. */ @@ -1082,7 +1087,7 @@ int vcterm; /* Set if terminal is a virtual console. */ F = fopen(opt_sn_name, opt_snap ? "w" : "a"); if (!F) { perror(opt_sn_name); - fprintf(stderr,"setterm: can not open dump file %s for output\n", + fprintf(stderr,("setterm: can not open dump file %s for output\n"), opt_sn_name); exit(-1); } @@ -1100,7 +1105,7 @@ int vcterm; /* Set if terminal is a virtual console. */ result = klogctl(6, NULL, 0); if (result != 0) - printf("klogctl error: %s\n", strerror(result)); + printf(_("klogctl error: %s\n"), strerror(result)); } /* -msglevel [0-8] */ @@ -1108,7 +1113,7 @@ int vcterm; /* Set if terminal is a virtual console. */ /* 8 -- Set level of messages printed to console */ result = klogctl(8, NULL, opt_msglevel_num); if (result != 0) - printf("klogctl error: %s\n", strerror(result)); + printf(_("klogctl error: %s\n"), strerror(result)); } /* -blength [0-2000] */ @@ -1145,11 +1150,11 @@ screendump(int vcnum, FILE *F){ inbuf = malloc(rows*cols*2); outbuf = malloc(rows*(cols+1)); if(!inbuf || !outbuf) { - fprintf(stderr, "Out of memory\n"); + fputs(_("Out of memory"), stderr); exit(1); } if (read(fd, inbuf, rows*cols*2) != rows*cols*2) { - fprintf(stderr, "Error reading %s\n", infile); + fprintf(stderr, _("Error reading %s\n"), infile); exit(1); } p = inbuf; @@ -1164,7 +1169,7 @@ screendump(int vcnum, FILE *F){ *q++ = '\n'; } if (fwrite(outbuf, 1, q-outbuf, F) != q-outbuf) { - fprintf(stderr, "Error writing screendump\n"); + fprintf(stderr, _("Error writing screendump\n")); exit(1); } return; @@ -1178,7 +1183,7 @@ try_ioctl: screenbuf[0] = 0; screenbuf[1] = (unsigned char) vcnum; if (ioctl(0,TIOCLINUX,screenbuf) < 0) { - fprintf(stderr,"couldn't read %s, and cannot ioctl dump\n", + fprintf(stderr,_("couldn't read %s, and cannot ioctl dump\n"), infile); exit(1); } @@ -1203,6 +1208,10 @@ int main(int argc, char **argv) char *term; /* Terminal type. */ int vcterm; /* Set if terminal is a virtual console. */ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + if (argc < 2) bad_arg = TRUE; /* Parse arguments. */ @@ -1239,7 +1248,7 @@ int main(int argc, char **argv) } else { term = getenv("TERM"); if (term == NULL) { - fprintf(stderr, "%s: $TERM is not defined.\n", argv[0]); + fprintf(stderr, _("%s: $TERM is not defined.\n"), argv[0]); exit(1); } } diff --git a/misc-utils/tsort.c b/misc-utils/tsort.c index 61e9e844..62789766 100644 --- a/misc-utils/tsort.c +++ b/misc-utils/tsort.c @@ -34,11 +34,16 @@ * SUCH DAMAGE. */ + /* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + #include #include #include #include #include +#include "nls.h" /* * Topological sort. Input is a list of pairs of strings seperated by @@ -102,12 +107,16 @@ main(argc, argv) int bsize, nused; BUF bufs[2]; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + if (argc < 2) fp = stdin; /* == becomes > in next line per Volker Meyer_zu_Bexten -- faith@cs.unc.edu, Sat Feb 4 21:25:09 1995 */ else if (argc > 2) { - (void)fprintf(stderr, "usage: tsort [ inputfile ]\n"); + (void)fprintf(stderr, _("usage: tsort [ inputfile ]\n")); exit(1); } else if (!(fp = fopen(argv[1], "r"))) { (void)fprintf(stderr, "tsort: %s.\n", strerror(errno)); @@ -144,7 +153,7 @@ main(argc, argv) } (void)fclose(fp); if (n) { - (void)fprintf(stderr, "tsort: odd data count.\n"); + (void)fprintf(stderr, _("tsort: odd data count.\n")); exit(1); } @@ -309,7 +318,7 @@ tsort() register int i; (void)fprintf(stderr, - "tsort: cycle in data.\n"); + _("tsort: cycle in data.\n")); for (i = 0; i < cnt; i++) (void)fprintf(stderr, "tsort: %s.\n", longest_cycle[i]->n_name); @@ -322,7 +331,7 @@ tsort() if (!n) { (void)fprintf(stderr, - "tsort: internal error -- could not find cycle.\n"); + _("tsort: internal error -- could not find cycle.\n")); exit(1); } } diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c index 49419241..cb07bc68 100644 --- a/misc-utils/whereis.c +++ b/misc-utils/whereis.c @@ -33,12 +33,17 @@ /* *:aeb */ +/* 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + */ + #include #include #include #include #include #include +#include "nls.h" void zerof(void); void getlist(int *, char ***, char ***, int *); @@ -142,11 +147,15 @@ main(argc, argv) int argc; char *argv[]; { + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + argc--, argv++; if (argc == 0) { usage: - fprintf(stderr, "whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n"); + fprintf(stderr, _("whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n")); exit(1); } do @@ -328,6 +337,9 @@ findin(char *dir, char *cp) { if (dirp == NULL) return; while ((dp = readdir(dirp)) != NULL) { + if (!strcmp(dp->d_name, ".") || + !strcmp(dp->d_name, "..")) + continue; if (strlen(dp->d_name) + l > sizeof(dirbuf)) continue; sprintf(d, "%s", dp->d_name); diff --git a/misc-utils/write.c b/misc-utils/write.c index 07a113ea..cac26239 100644 --- a/misc-utils/write.c +++ b/misc-utils/write.c @@ -40,6 +40,9 @@ * - Added fix from David.Chapell@mail.trincoll.edu enabeling daemons * to use write. * - ANSIed it since I was working on it anyway. + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * */ #include @@ -58,7 +61,8 @@ #include #include "pathnames.h" #endif - +#include "nls.h" + void search_utmp(char *, char *, char *, uid_t); void do_write(char *, char *, uid_t); void wr_fputs(char *); @@ -70,14 +74,15 @@ extern int errno; int main(int argc, char **argv) { - register char *cp; time_t atime; uid_t myuid; int msgsok, myttyfd; char tty[MAXPATHLEN], *mytty, *ttyname(); void done(); - setlocale(LC_CTYPE,""); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); /* check that sender has write enabled */ if (isatty(fileno(stdin))) @@ -91,16 +96,18 @@ main(int argc, char **argv) } if (myttyfd != -1) { if (!(mytty = ttyname(myttyfd))) { - (void)fprintf(stderr, "write: can't find your tty's name\n"); + (void)fprintf(stderr, _("write: can't find your tty's name\n")); exit(1); } - if ((cp = rindex(mytty, '/')) != NULL) - mytty = cp + 1; + /* We may have /dev/ttyN but also /dev/pts/xx. + Below, term_chk() will put "/dev/" in front, so remove that part. */ + if (!strncmp(mytty, "/dev/", 5)) + mytty += 5; if (term_chk(mytty, &msgsok, &atime, 1)) exit(1); if (!msgsok) { (void)fprintf(stderr, - "write: you have write permission turned off.\n"); + _("write: you have write permission turned off.\n")); exit(1); } @@ -121,7 +128,7 @@ main(int argc, char **argv) argv[2] += 5; if (utmp_chk(argv[1], argv[2])) { (void)fprintf(stderr, - "write: %s is not logged in on %s.\n", + _("write: %s is not logged in on %s.\n"), argv[1], argv[2]); exit(1); } @@ -129,14 +136,14 @@ main(int argc, char **argv) exit(1); if (myuid && !msgsok) { (void)fprintf(stderr, - "write: %s has messages disabled on %s\n", + _("write: %s has messages disabled on %s\n"), argv[1], argv[2]); exit(1); } do_write(argv[2], mytty, myuid); break; default: - (void)fprintf(stderr, "usage: write user [tty]\n"); + (void)fprintf(stderr, _("usage: write user [tty]\n")); exit(1); } done(); @@ -235,7 +242,7 @@ void search_utmp(char *user, char *tty, char *mytty, uid_t myuid) endutent(); if (nloggedttys == 0) { - (void)fprintf(stderr, "write: %s is not logged in\n", user); + (void)fprintf(stderr, _("write: %s is not logged in\n"), user); exit(1); } if (nttys == 0) { @@ -244,11 +251,11 @@ void search_utmp(char *user, char *tty, char *mytty, uid_t myuid) return; } (void)fprintf(stderr, - "write: %s has messages disabled\n", user); + _("write: %s has messages disabled\n"), user); exit(1); } else if (nttys > 1) { (void)fprintf(stderr, - "write: %s is logged in more than once; writing to %s\n", + _("write: %s is logged in more than once; writing to %s\n"), user, tty); } } @@ -314,8 +321,10 @@ void do_write(char *tty, char *mytty, uid_t myuid) now = time((time_t *)NULL); nows = ctime(&now); nows[16] = '\0'; - (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", + printf("\r\n\007\007\007"); + (void)printf(_("Message from %s@%s on %s at %s ..."), login, host, mytty, nows + 11); + printf("\r\n"); while (fgets(line, sizeof(line), stdin) != NULL) wr_fputs(line); diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 00000000..a01481be --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/mount/Makefile b/mount/Makefile index c61b4ae8..0d370ff8 100644 --- a/mount/Makefile +++ b/mount/Makefile @@ -1,6 +1,5 @@ -ifeq (../MCONFIG,$(wildcard ../MCONFIG)) +include ../make_include include ../MCONFIG -endif CC = gcc CFLAGS = -I$(LIB) $(OPT) diff --git a/mount/Makefile.standalone b/mount/Makefile.standalone deleted file mode 100644 index 1be37568..00000000 --- a/mount/Makefile.standalone +++ /dev/null @@ -1,141 +0,0 @@ -# ifeq (../MCONFIG,$(wildcard ../MCONFIG)) -# include ../MCONFIG -# endif - -# For now: a standalone version - -CC = gcc -CFLAGS = -O2 -I../lib - -#WARNFLAGS = -Wall -Wstrict-prototypes -# We really want -WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes -# but at the moment that yields -#:72: warning: no previous prototype for `cmsg_nxthdr' - -# you need rpcgen and libc-4.2 or rpclib to compile in the NFS support -# pregenerated files are included. -# Make sure nfsmount_clnt.c is newer than nfsmount.x to avoid gcc complaints. -DEFINES = -DHAVE_NFS - -RPCSVCDIR = rpcsvc -RPC_CFLAGS = -Wno-unused -RPCGEN = rpcgen - -INSTALL = install -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) -BINDIR = /bin -## for nosuid progs (swapon) -SBINDIR = /sbin - -# End of configuration section. - -COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES) -LINK = $(CC) $(LDFLAGS) - -SUID_PROGS = mount umount -NOSUID_PROGS = swapon losetup -PROGS = $(SUID_PROGS) $(NOSUID_PROGS) -MAN5 = fstab.5 nfs.5 -MAN8 = mount.8 swapoff.8 swapon.8 umount.8 losetup.8 - -# comment these out if you are not compiling in NFS support -NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o -# uncomment this if you don't have libc-4.2 but do have the rpclib -GEN_FILES = nfsmount.x nfsmount.h nfsmount_xdr.c nfsmount_clnt.c - -# comment these out if you are not compiling in loop support -LO_OBJS=lomount.o - -all: $(PROGS) - -install: $(PROGS) - $(INSTALLDIR) $(BINDIR) $(SBINDIR) - $(INSTALLSUID) -s $(SUID_PROGS) $(BINDIR) - $(INSTALLPROG) -s $(NOSUID_PROGS) $(SBINDIR) - (cd $(SBINDIR); ln -sf swapon swapoff) - $(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 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 mntent.o version.o $(LO_OBJS) - $(LINK) $^ -o $@ - -swapon: swapon.o version.o - $(LINK) $^ -o $@ - -losetup: losetup.o - $(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 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 - -nfsmount_xdr.o: nfsmount_xdr.c - $(COMPILE) $(RPC_CFLAGS) nfsmount_xdr.c - -nfsmount.h nfsmount_xdr.c nfsmount_clnt.c: nfsmount.x - rm -f nfsmount.h nfsmount_xdr.c nfsmount_clnt.c - $(RPCGEN) -h -o nfsmount.h nfsmount.x - $(RPCGEN) -c -o nfsmount_xdr.c nfsmount.x - $(RPCGEN) -l -o nfsmount_clnt.c nfsmount.x - -nfsmount.x: - cp $(RPCSVCDIR)/nfsmount.x . - -nfsmount.o: nfs_mountversion.h nfs_mount3.h - -NFSMOUNTH=/usr/include/linux/nfs_mount.h - -nfs_mountversion.h: - rm -f nfs_mountversion.h - if [ -f $(NFSMOUNTH) ]; then \ - grep NFS_MOUNT_VERSION $(NFSMOUNTH) \ - | sed -e 's/NFS/KERNEL_NFS/'; \ - else \ - echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \ - fi > nfs_mountversion.h - -swapargs.h: - sh swap.configure - -loop.h: - sh mk_loop_h - -clean: - rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff - 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 d343538d..5b85fb99 100644 --- a/mount/fstab.5 +++ b/mount/fstab.5 @@ -37,8 +37,9 @@ .\" Sat Nov 27 20:23:32 1993: Updated authorship information .\" Wed Jul 26 00:00:00 1995: Updated some nfs stuff, joey@infodrom.north.de .\" Tue Apr 2 00:38:28 1996: added info about "noauto", "user", etc. +.\" Tue Jun 15 20:02:18 1999: added LABEL and UUID .\" -.TH FSTAB 5 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual" +.TH FSTAB 5 "15 June 1999" "Linux 2.2" "Linux Programmer's Manual" .SH NAME fstab \- static information about the filesystems .SH SYNOPSIS @@ -66,11 +67,28 @@ The first field, .RI ( fs_spec ), describes the block special device or remote filesystem to be mounted. +.LP +For ordinary mounts it will hold (a link to) a block special +device node (as created by +.BR mknod (8)) +for the device to be mounted, like `/dev/cdrom' or `/dev/sdb7'. +For NFS mounts one will have :

, e.g., `knuth.aeb.nl:/'. +For procfs, use `proc'. +.LP +Instead of giving the device explicitly, one may indicate +the (ext2) filesystem that is to be mounted by its UUID or +volume label (cf. +.BR e2label (8)), +writing LABEL=