Imported from util-linux-2.10f tarball.

This commit is contained in:
Karel Zak 2006-12-07 00:25:41 +01:00
parent 7eda085c41
commit eb63b9b8f4
129 changed files with 24647 additions and 15787 deletions

88
HISTORY
View file

@ -1,3 +1,88 @@
util-linux 2.10f:
* Security fix for mount (okir)
* Avoid infinite loop in namei (Brett Wuth)
* added clock-ppc.c (from Matsuura Takanori), not merged yet
* deleted clockB subdirectory
* recognize mkdosfs string (Michal Svec)
util-linux 2.10e:
* New: rename
* Added option to mkswap so that user can override pagesize
* fdisk -l now reads /proc/partitions when no device was given
* Fixed fdisk.8 (James Manning)
* Added devpts info to mount.8 (Elrond)
* Newline fix for logger output to stdout (Henri Spencer)
util-linux 2.10d:
* Do not try to mount something as udf without good reason
* Do not loop in umount if there is a stale lock file
* Allow fdisk twice as many cylinders
* Fixed non-casefolding search in look (Markus Demleitner)
util-linux 2.10c:
* Various compilation fixes
util-linux 2.10b:
* Fixed smbmount problem (Andrew Tridgell)
* Fixed ddate problem with the day after St. Tib's Day (Brad)
* German messages (Elrond)
* Made kill a bit more standard compliant
* Made some more programs output a version
util-linux 2.10a:
* Japanese messages (Daisuke Yamashita)
* French messages and several Debian fixes (Vincent Renardias)
* Fixed infinite loop in mkfs.minix
util-linux 2.10:
* Added BSD disklabel code to rescuept
* Added blockdev utility
* Fix losetup return code
* Fix unit display in cfdisk
* Do not redefine _PATH_MAILDIR (so that recent systems can have /var/mail)
* Added --localtime option to hwclock;
added third line (LOCAL/UTC) to /etc/adjtime.
* Add -H option to agetty (David Holland)
util-linux 2.9z:
* Japanese messages (Daisuke Yamashita)
* Czech messages (Jiri Pavlovsky)
* Added some udf stuff to mount.8
* Added ioctl for fdisk on bsdlabels
util-linux 2.9y:
* Wide character support (Bruno Haible)
* German messages and some small fixes (Elrond)
* Small fix to owner mount option (Erik Troan)
* Don't sleep so long in clock/kd.c (Christian T. Steigies)
util-linux 2.9x:
* German messages and a i18n fix (Elrond)
* mount option: allow the owner to mount a device (RedHat)
* ugly: let login open console with O_NONBLOCK (Maciej W. Rozycki)
* UGLY: let login ignore mail that is precisely 523 bytes long (RedHat)
* added mkfs.bfs, mkfs.bfs.8
* mount now recognizes qnx4 and bfs partitions
* rescuept now recognizes Unixware partitions
* hwclock fix on m68k (Roman Hodek)
* several minor things
util-linux 2.9w:
* Updated mount.8 (Yann Droneaud)
* Improved makefiles
* Fixed flaw in fdisk
util-linux 2.9v:
* cfdisk no longer believes the kernel's HDGETGEO
@ -31,6 +116,7 @@ util-linux 2.9t:
util-linux 2.9s:
* tunelp patch (Andrea Arcangeli)
* fixed mount race (HJLu)
* German messages (Elrond)
util-linux 2.9[pqr]:
@ -66,8 +152,8 @@ util-linux 2.9l:
util-linux 2.9k:
* major reshuffle of hwclock stuff; added sparc and alpha code
* fdisk fix
* tiny shutdown fix
* tiny fdisk fix
util-linux 2.9j:

29
INSTALL
View file

@ -21,8 +21,8 @@ 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.9X.tar.gz somewhere
3) cd util-linux-2.9X
2) Untar util-linux-2.10X.tar.gz somewhere
3) cd util-linux-2.10X
4) Edit MCONFIG
5) ./configure
6) Look at defines.h and make_include, and edit if necessary
@ -37,15 +37,30 @@ To install from source:
If you have compilation problems: tell util-linux@math.uio.no about it.
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.
A glibc header bug causes
/usr/include/bits/string2.h:419: warning: pointer of type `void *'
used in arithmetic
This is harmless.
Some old libc have complaints like
Users of libc5 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.
Several old libc have complaints like
/usr/include/sys/syslog.h:71: warning: missing braces around initializer
/usr/include/rpc/xdr.h:103: warning: function declaration isn't a prototype
/usr/include/rpc/auth.h:86: warning: function declaration isn't a prototype
/usr/include/rpc/svc.h:79: warning: function declaration isn't a prototype
Also this is a libc/include problem.
Warnings like
<sys/mman.h>:11: warning: `MAP_FILE' redefined
<asm/mman.h>:30: warning: this is the location of the previous definition
are caused by the libc/kernel combination.
All such warnings are harmless.
There should be no compilation errors.

2
MAINTAINER Normal file
View file

@ -0,0 +1,2 @@
Maintainer: Andries Brouwer (aeb@cwi.nl)
Maintainer address: util-linux@math.uio.no

24
MCONFIG
View file

@ -8,7 +8,7 @@
# - define DESTDIR
# Select for CPU one of intel, alpha, sparc, arm, m68k, mips
CPU=$(shell uname -m | sed s/i.86/intel/)
CPU=$(shell uname -m | sed 's/i.86/intel/;s/arm.*/arm/')
# define where is locale directrory (default /usr/share/locale)
LOCALEDIR=/usr/share/locale
@ -74,25 +74,36 @@ HAVE_RESET=yes
# sln also comes with libc and glibc.
HAVE_SLN=no
# If HAVE_TSORT is set to "yes", then tsort won't be installed.
# GNU textutils 2.0 includes tsort.
HAVE_TSORT=no
# If HAVE_FDUTILS is set to "yes", then setfdprm won't be installed.
HAVE_FDUTILS=no
# Get CC from environment if defined
ifeq "$(CC)" ""
CC= gcc
endif
# Different optimizations for different cpus.
ifeq "$(CPU)" "intel"
OPT= -pipe -O2 -m486 -fomit-frame-pointer
else
ifeq "$(CPU)" "arm"
OPT= -O2 -m3 -fomit-frame-pointer
OPT= -pipe -O2 -fsigned-char -fomit-frame-pointer
else
OPT= -O2 -fomit-frame-pointer
endif
endif
ERR_O=$(LIB)/err.o
LDFLAGS = -s
WARNFLAGS = -Wall
LIB=../lib
LDFLAGS = -s
WARNFLAGS = -Wall
ERR_O=$(LIB)/err.o
CFLAGS = $(OPT) -I. -I$(LIB) $(WARNFLAGS) \
$(CURSESFLAGS) $(SLANGFLAGS) \
@ -141,6 +152,9 @@ FSCKDIR= $(SBINDIR)
# Directory for passwd
PASSWDDIR= $(USRBINDIR)
# Directory for help file for more. Some may want /usr/share/misc .
MOREHELPDIR= $(USRLIBDIR)
# Modes
DIRMODE= 755
BINMODE= 755

View file

@ -5,8 +5,6 @@
# May be distributed under the terms of the GNU GPL.
#
VERSION=2.9
include ./make_include
include ./MCONFIG
@ -24,7 +22,7 @@ SUBDIRS=po \
text-utils \
kbd
.PHONEY: all install clean
.PHONEY: all install clean now
all: defines.h
@for subdir in $(SUBDIRS); do \
(cd $$subdir && $(MAKE) $@) || exit 1; \
@ -33,6 +31,12 @@ all: defines.h
defines.h make_include:
./configure
now:
touch defines.h
$(SUBDIRS): defines.h now
cd $@ && $(MAKE)
install:
@if [ "`whoami`" = "root" ]; then umask 022; fi
@for subdir in $(SUBDIRS); do \
@ -49,17 +53,20 @@ distclean: make_include clean
cd po && make distclean
-rm -f defines.h make_include
dist:
(cd /tmp; \
rm -rf /tmp/util-linux-$(VERSION); \
cvs export -fNd util-linux-$(VERSION) -r HEAD util-linux; \
cd util-linux-$(VERSION); \
find -type d | xargs chmod 755; \
find -type f | xargs chmod 644; \
find -type d | xargs chown root:root; \
find -type f | xargs chown root:root; \
cd ..; \
GZIP=-9 tar cvvzf util-linux-$(VERSION).tar.gz util-linux-$(VERSION); \
cp -p util-linux-$(VERSION)/LSM util-linux-$(VERSION).lsm; \
cp -p util-linux-$(VERSION)/ANNOUNCE util-linux-$(VERSION).Announce; \
echo Done.)
#
# dist:
# (cd /tmp; \
# rm -rf /tmp/util-linux-$(VERSION); \
# cvs export -fNd util-linux-$(VERSION) -r HEAD util-linux; \
# cd util-linux-$(VERSION); \
# find -type d | xargs chmod 755; \
# find -type f | xargs chmod 644; \
# find -type d | xargs chown root:root; \
# find -type f | xargs chown root:root; \
# cd ..; \
# GZIP=-9 tar cvvzf util-linux-$(VERSION).tar.gz util-linux-$(VERSION); \
# cp -p util-linux-$(VERSION)/LSM util-linux-$(VERSION).lsm; \
# cp -p util-linux-$(VERSION)/ANNOUNCE util-linux-$(VERSION).Announce; \
# echo Done.)
#

View file

@ -1,39 +0,0 @@
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

1
VERSION Normal file
View file

@ -0,0 +1 @@
2.10f

View file

@ -2,21 +2,11 @@ Hwclock is a program that runs under Linux and sets and queries the
Hardware Clock, which is often called the Real Time Clock, RTC, or
CMOS clock.
Hwclock is shipped with an ELF executable built for ISA (Intel)
machines. So there is nothing to build for those machines. Just
install the executable file "hwclock" and the man page file
"hwclock.8" in suitable directories (like /sbin/hwclock and
/usr/man/man8/hwclock.8) and you're ready to go.
hwclock accesses platform-dependent hardware, so if you have something
other than an ISA machine, the shipped executable probably doesn't work,
and you have to compile hwclock yourself.
Sometimes, you need to install hwclock setuid root. If you want users
other than the superuser to be able to display the clock value using the
direct ISA I/O method, install it setuid root. If you have the /dev/rtc
interface on your system or are on a non-ISA system, there's no need for
users to use the direct ISA I/O method, so don't bother.
interface on your system or are on a non-ISA system, there's probably
no need for users to use the direct ISA I/O method, so don't bother.
To install setuid root, do something like this:
@ -32,15 +22,6 @@ If you want to build hwclock, just cd to the source directory and invoke
make with no parameters.
hwclock calls option processing routines in the libsshopt library,
which is part of Sverre H. Huseby's "shhopt" package. An ELF
executable of this library is included in the package, but you can use
a copy that is already on your system by altering the make file. You
can find a more authoritative copy of this library, and its source
code, on sunsite (ftp://sunsite.unc.edu/pub/Linux/libs/shhopt-X.Y).
As shipped, the routines are linked in statically, so you only need the
libsshopt.a file to build hwclock, not to run it.
which is part of Sverre H. Huseby's "shhopt" package. You
can find a more authoritative copy of this package on metalab
(ftp://metalab.unc.edu/pub/Linux/libs/shhopt-X.Y).

459
clock/clock-ppc.c Normal file
View file

@ -0,0 +1,459 @@
/*
From t-matsuu@protein.osaka-u.ac.jp Sat Jan 22 13:43:20 2000
Date: Sat, 22 Jan 2000 21:42:54 +0900 (JST)
To: Andries.Brouwer@cwi.nl
Subject: Please merge the source for PPC
From: MATSUURA Takanori <t-matsuu@protein.osaka-u.ac.jp>
Even now, it is used clock-1.1 based source on Linux for PowerPC
architecture, attached on this mail.
Please merge this source in main util-linux source.
But I'm not an author of this source, but Paul Mackerras.
http://linuxcare.com.au/paulus/
shows details of him.
MATSUURA Takanori @ Division of Protein Chemistry,
Institute for Protein Research, Osaka University, Japan
E-Mail: t-matsuu@protein.osaka-u.ac.jp
Web Page: http://www.protein.osaka-u.ac.jp/chemistry/matsuura/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/time.h>
#include <asm/cuda.h>
/*
* Adapted for Power Macintosh by Paul Mackerras.
*/
/* V1.0
* CMOS clock manipulation - Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992
*
* clock [-u] -r - read cmos clock
* clock [-u] -w - write cmos clock from system time
* clock [-u] -s - set system time from cmos clock
* clock [-u] -a - set system time from cmos clock, adjust the time to
* correct for systematic error, and put it back to the cmos.
* -u indicates cmos clock is kept in universal time
*
* The program is designed to run setuid, since we need to be able to
* write to the CUDA.
*
*********************
* 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.
*
* I think a small explanation of the adjustment routine should be given
* here. 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'
*
* If the adjustment doesn't work for you, try contacting me by E-mail.
*
******
* 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.
*
* August 1996 Tom Dyas (tdyas@eden.rutgers.edu)
* Converted to be compatible with the SPARC /dev/rtc driver.
*
*/
#define VERSION "1.4"
/* Here the information for time adjustments is kept. */
#define ADJPATH "/etc/adjtime"
/* Apparently the RTC on PowerMacs stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800
/* used for debugging the code. */
/*#define KEEP_OFF */
/* Globals */
int readit = 0;
int adjustit = 0;
int writeit = 0;
int setit = 0;
int universal = 0;
int debug = 0;
time_t mkgmtime(struct tm *);
volatile void
usage ( void )
{
(void) fprintf (stderr,
"clock [-u] -r|w|s|a|v\n"
" r: read and print CMOS clock\n"
" w: write CMOS clock from system time\n"
" s: set system time from CMOS clock\n"
" a: get system time and adjust CMOS clock\n"
" u: CMOS clock is in universal time\n"
" v: print version (" VERSION ") and exit\n"
);
exit(EXIT_FAILURE);
}
int adb_fd;
void
adb_init ( void )
{
adb_fd = open ("/dev/adb", 2);
if (adb_fd < 0)
{
perror ("unable to open /dev/adb read/write : ");
exit(EXIT_FAILURE);
}
}
unsigned char get_packet[2] = { (unsigned char) CUDA_PACKET,
(unsigned char) CUDA_GET_TIME };
unsigned char set_packet[6] = { (unsigned char) CUDA_PACKET,
(unsigned char) CUDA_SET_TIME };
int
main (int argc, char **argv )
{
struct tm tm, *tmp;
time_t systime;
time_t last_time;
time_t clock_time;
int i, arg;
double factor;
double not_adjusted;
int adjustment = 0;
/* unsigned char save_control, save_freq_select; */
unsigned char reply[16];
while ((arg = getopt (argc, argv, "rwsuaDv")) != -1)
{
switch (arg)
{
case 'r':
readit = 1;
break;
case 'w':
writeit = 1;
break;
case 's':
setit = 1;
break;
case 'u':
universal = 1;
break;
case 'a':
adjustit = 1;
break;
case 'D':
debug = 1;
break;
case 'v':
(void) fprintf( stderr, "clock " VERSION "\n" );
exit(EXIT_SUCCESS);
default:
usage ();
}
}
/* If we are in MkLinux do not even bother trying to set the clock */
if(!access("/proc/osfmach3/version", R_OK))
{ // We're running MkLinux
if ( readit | writeit | setit | adjustit )
printf("You must change the clock setting in MacOS.\n");
exit(0);
}
if (readit + writeit + setit + adjustit > 1)
usage (); /* only allow one of these */
if (!(readit | writeit | setit | adjustit)) /* default to read */
readit = 1;
adb_init ();
if (adjustit)
{ /* Read adjustment parameters first */
FILE *adj;
if ((adj = fopen (ADJPATH, "r")) == NULL)
{
perror (ADJPATH);
exit(EXIT_FAILURE);
}
if (fscanf (adj, "%lf %d %lf", &factor, (int *) (&last_time),
&not_adjusted) < 0)
{
perror (ADJPATH);
exit(EXIT_FAILURE);
}
(void) fclose (adj);
if (debug) (void) printf(
"Last adjustment done at %d seconds after 1/1/1970\n",
(int) last_time);
}
if (readit || setit || adjustit)
{
int ii;
if (write(adb_fd, get_packet, sizeof(get_packet)) < 0) {
perror("write adb");
exit(EXIT_FAILURE);
}
ii = (int) read(adb_fd, reply, sizeof(reply));
if (ii < 0) {
perror("read adb");
exit(EXIT_FAILURE);
}
if (ii != 7)
(void) fprintf(stderr,
"Warning: bad reply length from CUDA (%d)\n", ii);
clock_time = (time_t) ((reply[3] << 24) + (reply[4] << 16)
+ (reply[5] << 8)) + (time_t) reply[6];
clock_time -= RTC_OFFSET;
if (universal) {
systime = clock_time;
} else {
tm = *gmtime(&clock_time);
(void) printf("time in rtc is %s", asctime(&tm));
tm.tm_isdst = -1; /* don't know whether it's DST */
systime = mktime(&tm);
}
}
if (readit)
{
(void) printf ("%s", ctime (&systime ));
}
if (setit || adjustit)
{
struct timeval tv;
struct timezone tz;
/* program is designed to run setuid, be secure! */
if (getuid () != 0)
{
(void) fprintf (stderr,
"Sorry, must be root to set or adjust time\n");
exit(EXIT_FAILURE);
}
if (adjustit)
{ /* the actual adjustment */
double exact_adjustment;
exact_adjustment = ((double) (systime - last_time))
* factor / (24 * 60 * 60)
+ not_adjusted;
if (exact_adjustment > 0.)
adjustment = (int) (exact_adjustment + 0.5);
else
adjustment = (int) (exact_adjustment - 0.5);
not_adjusted = exact_adjustment - (double) adjustment;
systime += adjustment;
if (debug) {
(void) printf ("Time since last adjustment is %d seconds\n",
(int) (systime - last_time));
(void) printf ("Adjusting time by %d seconds\n",
adjustment);
(void) printf ("remaining adjustment is %.3f seconds\n",
not_adjusted);
}
}
#ifndef KEEP_OFF
tv.tv_sec = systime;
tv.tv_usec = 0;
tz.tz_minuteswest = timezone / 60;
tz.tz_dsttime = daylight;
if (settimeofday (&tv, &tz) != 0)
{
(void) fprintf (stderr,
"Unable to set time -- probably you are not root\n");
exit(EXIT_FAILURE);
}
if (debug) {
(void) printf( "Called settimeofday:\n" );
(void) printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n",
tv.tv_sec, tv.tv_usec );
(void) printf( "\ttz.tz_minuteswest = %d, tz.tz_dsttime = %d\n",
tz.tz_minuteswest, tz.tz_dsttime );
}
#endif
}
if (writeit || (adjustit && adjustment != 0))
{
systime = time (NULL);
if (universal) {
clock_time = systime;
} else {
tmp = localtime(&systime);
clock_time = mkgmtime(tmp);
}
clock_time += RTC_OFFSET;
set_packet[2] = clock_time >> 24;
set_packet[3] = clock_time >> 16;
set_packet[4] = clock_time >> 8;
set_packet[5] = (unsigned char) clock_time;
if (write(adb_fd, set_packet, sizeof(set_packet)) < 0) {
perror("write adb (set)");
exit(EXIT_FAILURE);
}
i = (int) read(adb_fd, reply, sizeof(reply));
if (debug) {
int j;
(void) printf("set reply %d bytes:", i);
for (j = 0; j < i; ++j)
(void) printf(" %.2x", (unsigned int) reply[j]);
(void) printf("\n");
}
if (i != 3 || reply[1] != (unsigned char) 0)
(void) fprintf(stderr, "Warning: error %d setting RTC\n",
(int) reply[1]);
if (debug) {
clock_time -= RTC_OFFSET;
(void) printf("set RTC to %s", asctime(gmtime(&clock_time)));
}
}
else
if (debug) (void) printf ("CMOS clock unchanged.\n");
/* Save data for next 'adjustit' call */
if (adjustit)
{
FILE *adj;
if ((adj = fopen (ADJPATH, "w")) == NULL)
{
perror (ADJPATH);
exit(EXIT_FAILURE);
}
(void) fprintf (adj, "%f %d %f\n", factor, (int) systime, not_adjusted);
(void) fclose (adj);
}
exit(EXIT_SUCCESS);
}
/* Stolen from linux/arch/i386/kernel/time.c. */
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
*
* [For the Julian calendar (which was used in Russia before 1917,
* Britain & colonies before 1752, anywhere else before 1582,
* and is still in use by some communities) leave out the
* -year/100+year/400 terms, and add 10.]
*
* This algorithm was first published by Gauss (I think).
*
* WARNING: this function will overflow on 2106-02-07 06:28:16 on
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
time_t mkgmtime(struct tm *tm)
{
int mon = tm->tm_mon + 1;
int year = tm->tm_year + 1900;
if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
return (((
(unsigned long)(year/4 - year/100 + year/400 + 367*mon/12) +
tm->tm_mday + year*365 - 719499
)*24 + tm->tm_hour /* now have hours */
)*60 + tm->tm_min /* now have minutes */
)*60 + tm->tm_sec; /* finally seconds */
}

View file

@ -146,8 +146,9 @@ set_cmos_epoch(int ARCconsole, int SRM) {
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.
/* See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or BX),
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;

View file

@ -2,34 +2,35 @@
.SH NAME
clock \- query and set the hardware clock (RTC)
.SH SYNOPSIS
.B "hwclock --show"
.B "hwclock \-\-show"
.br
.B "hwclock --set --date=newdate"
.B "hwclock \-\-set \-\-date=newdate"
.br
.B "hwclock --systohc"
.B "hwclock \-\-systohc"
.br
.B "hwclock --hctosys"
.B "hwclock \-\-hctosys"
.br
.B "hwclock --getepoch"
.B "hwclock \-\-getepoch"
.br
.B "hwclock --setepoch --epoch=year"
.B "hwclock \-\-setepoch \-\-epoch=year"
.br
.B "hwclock --adjust"
.B "hwclock \-\-adjust"
.br
.B "hwclock --version"
.B "hwclock \-\-version"
.PP
other options:
.PP
.B "--utc --localtime --directisa --test --debug"
.B "\-\-utc \-\-localtime \-\-directisa \-\-test \-\-debug"
.PP
and arcane options for DEC Alpha:
.PP
.B "--arc --jensen --srm --funky-toy"
.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".
Also, equivalent options \-r, \-w, \-s, \-a, \-v, \-u,
\-D, \-A, \-J, \-S, and \-F are accepted for compatibility
with the program "clock", while \-h asks for a help message.
.SH DESCRIPTION
.I hwclock
@ -239,7 +240,9 @@ 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
running on, at least when
.I /proc
is mounted. These options make it possible for
.I hwclock
to work even when
its environment does not conform to its expectations and thus it cannot
@ -259,10 +262,12 @@ automatically.
means you are running on a Jensen model.
.B \-\-arc
means your machine is running with ARC console time.
means your machine uses epoch 1980 in its hardware clock, as is commonly
the case for machines on ARC console (but Ruffians have epoch 1900).
.B \-\-srm
means your machine is running with SRM console time.
means your machine uses epoch 1900 in its hardware clock, as is commonly
the case for machines on SRM console.
.B \-\-funky\-toy
means that on your machine, one has to use the UF bit instead

View file

@ -75,9 +75,9 @@
#include <sys/time.h>
#include <sys/stat.h>
#include <shhopt.h>
#include <stdarg.h>
#include "clock.h"
#include "../version.h"
#include "nls.h"
#define MYNAME "hwclock"
@ -105,10 +105,18 @@ struct adjtime {
updated since read from the disk file).
*/
bool dirty;
/* line 1 */
float drift_factor;
time_t last_adj_time;
float not_adjusted;
/* line 2 */
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) */
/* line 3 */
enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc;
/* To which time zone, local or UTC, we most recently set the
hardware clock. */
};
bool debug;
@ -189,6 +197,25 @@ time_inc(struct timeval addend, float increment) {
}
static bool
hw_clock_is_utc(const bool utc, const bool local_opt,
const struct adjtime adjtime) {
bool ret;
if (utc)
ret = TRUE; /* --utc explicitly given on command line */
else if (local_opt)
ret = FALSE; /* --localtime explicitly given */
else
/* get info from adjtime file - default is local */
ret = (adjtime.local_utc == UTC);
if (debug)
printf(_("Assuming hardware clock is kept in %s time.\n"),
ret ? _("UTC") : _("local"));
return ret;
}
static void
read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
@ -214,6 +241,7 @@ read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
adjtime_p->last_adj_time = 0;
adjtime_p->not_adjusted = 0;
adjtime_p->last_calib_time = 0;
adjtime_p->local_utc = UNKNOWN;
*rc_p = 0;
} else {
@ -224,11 +252,14 @@ read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
} 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);
@ -245,6 +276,19 @@ read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time);
if (!strcmp(line3, "UTC\n"))
adjtime_p->local_utc = UTC;
else if (!strcmp(line3, "LOCAL\n"))
adjtime_p->local_utc = LOCAL;
else {
adjtime_p->local_utc = UNKNOWN;
if (line3[0]) {
fprintf(stderr, _("%s: Warning: unrecognized third line in adjtime file\n"),
MYNAME);
fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
}
}
*rc_p = 0;
}
adjtime_p->dirty = FALSE;
@ -254,6 +298,9 @@ read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
(int) adjtime_p->last_adj_time);
printf(_("Last calibration done at %d seconds after 1969\n"),
(int) adjtime_p->last_calib_time);
printf(_("Hardware clock is on %s time\n"),
(adjtime_p->local_utc == LOCAL) ? _("local") :
(adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown"));
}
}
}
@ -312,7 +359,6 @@ mktime_tz(struct tm tm, const bool universal,
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);
@ -340,7 +386,9 @@ mktime_tz(struct tm tm, const bool universal,
*valid_p = TRUE;
*systime_p = mktime_result;
if (debug)
printf(_("Hw clock time : %.2d:%.2d:%.2d = %d seconds since 1969\n"),
printf(_("Hw clock time : %2d/%.2d/%.2d %.2d:%.2d:%.2d = "
"%d seconds since 1969\n"),
tm.tm_year, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, (int) *systime_p);
}
/* now put back the original zone. */
@ -578,10 +626,7 @@ set_system_clock(const bool hclock_valid, const time_t 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.
tzset() would interpret them.
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
@ -590,7 +635,7 @@ set_system_clock(const bool hclock_valid, const time_t newtime,
If 'testing' is true, don't actually update anything -- just say we
would have.
-----------------------------------------------------------------------------*/
int retcode; /* our eventual return code */
int retcode;
if (!hclock_valid) {
fprintf(stderr,_("The Hardware Clock does not contain a valid time, so "
@ -598,21 +643,18 @@ set_system_clock(const bool hclock_valid, const time_t newtime,
retcode = 1;
} else {
struct timeval tv;
int rc; /* local return code */
int rc;
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'
*/
tzset(); /* init timezone from TZ or ...zoneinfo/localtime */
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);
printf( _("\ttz.tz_minuteswest = %ld\n"), timezone/60);
}
if (testing) {
printf(_("Not setting system clock because running in test mode.\n"));
@ -620,10 +662,11 @@ set_system_clock(const bool hclock_valid, const time_t newtime,
} 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 ... */
The code used to have `-60*daylight' here, but that is wrong.
The variable `daylight' does not specify whether it is DST now. */
const struct timezone tz = { timezone/60, 0 };
rc = settimeofday(&tv, &tz);
if (rc != 0) {
if (errno == EPERM)
@ -744,16 +787,17 @@ save_adjtime(const struct adjtime adjtime, const bool testing) {
But if the contents are clean (unchanged since read from disk), don't
bother.
-----------------------------------------------------------------------------*/
char newfile[405]; /* Stuff to write to disk file */
char newfile[412]; /* 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",
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 );
(long) adjtime.last_calib_time,
(adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
if (testing) {
printf(_("Not updating adjtime file because of testing mode.\n"));
@ -883,9 +927,8 @@ 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
) {
const bool utc, const bool local_opt,
const bool testing, int *retcode_p) {
/*---------------------------------------------------------------------------
Do all the normal work of hwclock - read, set clock, etc.
@ -902,7 +945,7 @@ manipulate_clock(const bool show, const bool adjust,
if (no_auth) *retcode_p = 1;
else {
if (adjust || set || systohc)
if (adjust || set || systohc || (!utc && !local_opt))
read_adjtime(&adjtime, &rc);
else {
/* A little trick to avoid reading the file if we don't have to */
@ -911,6 +954,14 @@ manipulate_clock(const bool show, const bool adjust,
}
if (rc != 0) *retcode_p = 2;
else {
const bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
if ((set || systohc || adjust) &&
(adjtime.local_utc == UTC) != universal) {
adjtime.local_utc = universal ? UTC : LOCAL;
adjtime.dirty = TRUE;
}
synchronize_to_clock_tick(retcode_p);
/* this takes up to 1 second */
if (*retcode_p == 0) {
@ -1016,6 +1067,66 @@ manipulate_epoch(const bool getepoch, const bool setepoch,
#endif
}
/*
usage - Output (error and) usage information
This function is called both directly from main to show usage
information and as fatal function from shhopt if some argument is
not understood. In case of normal usage info FMT should be NULL.
In that case the info is printed to stdout. If FMT is given
usage will act like fprintf( stderr, fmt, ... ), show a usage
information and terminate the program afterwards.
*/
static void
usage( const char *fmt, ... ) {
FILE *usageto;
va_list ap;
usageto = fmt ? stderr : stdout;
fprintf( usageto, _(
"hwclock - query and set the hardware clock (RTC)\n\n"
"Usage: hwclock [function] [options...]\n\n"
"Functions:\n"
" --help show this help\n"
" --show read hardware clock and print result\n"
" --set set the rtc to the time given with --date\n"
" --hctosys set the system time from the hardware clock\n"
" --systohc set the hardware clock to the current system time\n"
" --adjust adjust the rtc to account for systematic drift since \n"
" the clock was last set or adjusted\n"
" --getepoch print out the kernel's hardware clock epoch value\n"
" --setepoch set the kernel's hardware clock epoch value to the \n"
" value given with --epoch\n"
" --version print out the version of hwclock to stdout\n"
"\nOptions: \n"
" --utc the hardware clock is kept in coordinated universal time\n"
" --localtime the hardware clock is kept in local time\n"
" --directisa access the ISA bus directly instead of /dev/rtc\n"
" --badyear ignore rtc's year because the bios is broken\n"
" --date specifies the time to which to set the hardware clock\n"
" --epoch=year specifies the year which is the beginning of the \n"
" hardware clock's epoch value\n"
));
#ifdef __alpha__
fprintf( usageto, _(
" --jensen, --arc, --srm, --funky-toy\n"
" tell hwclock the type of alpha you have (see hwclock(8))\n"
) );
#endif
fflush(stdout);
if( fmt ) {
usageto = stderr;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
exit( fmt ? 99 : 0 );
}
int
main(int argc, char **argv, char **envp) {
@ -1034,12 +1145,14 @@ main(int argc, char **argv, char **envp) {
are given by the option_def. The only exception is <show>, 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;
bool help, show, set, systohc, hctosys, adjust, getepoch, setepoch, version;
bool ARCconsole, utc, testing, directisa, Jensen, SRM, funky_toy;
bool local_opt;
char *date_opt;
int epoch_opt;
const optStruct option_def[] = {
{ 'h', (char *) "help", OPT_FLAG, &help, 0 },
{ 'r', (char *) "show", OPT_FLAG, &show, 0 },
{ 0, (char *) "set", OPT_FLAG, &set, 0 },
{ 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 },
@ -1048,9 +1161,11 @@ main(int argc, char **argv, char **envp) {
{ 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 },
{ 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 },
{ 'v', (char *) "version", OPT_FLAG, &version, 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 },
{ '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 },
@ -1073,8 +1188,8 @@ main(int argc, char **argv, char **envp) {
textdomain(PACKAGE);
/* set option defaults */
show = set = systohc = hctosys = adjust = getepoch = setepoch =
version = universal = ARCconsole = SRM = funky_toy =
help = show = set = systohc = hctosys = adjust = getepoch = setepoch =
version = utc = local_opt = ARCconsole = SRM = funky_toy =
directisa = badyear = Jensen = testing = debug = FALSE;
date_opt = NULL;
epoch_opt = -1;
@ -1082,8 +1197,8 @@ main(int argc, char **argv, char **envp) {
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
Sets show, systohc, hctosys, adjust, utc, local_opt, 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
@ -1091,12 +1206,14 @@ main(int argc, char **argv, char **envp) {
getopt() and usage() and throw shhopt out. */
if (argc_parse - 1 > 0) {
fprintf(stderr, _("%s takes no non-option arguments. "
usage( _("%s takes no non-option arguments. "
"You supplied %d.\n"),
MYNAME, argc_parse - 1);
exit(100);
}
if (help)
usage( NULL );
if (show + set + systohc + hctosys + adjust +
getepoch + setepoch + version > 1) {
fprintf(stderr, _("You have specified multiple function options.\n"
@ -1104,6 +1221,12 @@ main(int argc, char **argv, char **envp) {
exit(100);
}
if (utc && local_opt) {
fprintf(stderr, _("%s: The --utc and --localtime options are mutually "
"exclusive. You specified both.\n"), MYNAME);
exit(100);
}
#ifdef __alpha__
set_cmos_epoch(ARCconsole, SRM);
set_cmos_access(Jensen, funky_toy);
@ -1145,6 +1268,8 @@ main(int argc, char **argv, char **envp) {
} else if (getepoch || setepoch) {
manipulate_epoch(getepoch, setepoch, epoch_opt, testing);
} else {
if (debug)
printf(MYNAME " " VERSION "/%s\n",util_linux_version);
determine_clock_access_method(directisa);
if (!ur)
fprintf(stderr, _("Cannot access the Hardware Clock via any known "
@ -1152,7 +1277,7 @@ main(int argc, char **argv, char **envp) {
"search for an access method.\n"));
else
manipulate_clock(show, adjust, set, set_time, hctosys, systohc,
startup_time, universal, testing, &rc);
startup_time, utc, local_opt, testing, &rc);
}
}
exit(retcode);
@ -1161,7 +1286,7 @@ main(int argc, char **argv, char **envp) {
/* A single routine for greater uniformity */
void
outsyserr(char *msg) {
fprintf(stderr, _("%s: %s, errno=%d: %s.\n"),
fprintf(stderr, "%s: %s, errno=%d: %s.\n",
progname, msg, errno, strerror(errno));
}

View file

@ -3,6 +3,7 @@
#include <fcntl.h> /* for O_RDONLY */
#include <sys/ioctl.h>
#include "../defines.h" /* for HAVE_nanosleep */
#include "clock.h"
#include "nls.h"
@ -46,6 +47,20 @@ synchronize_to_clock_tick_kd(void) {
i = 0;
do {
/* Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
/* "The culprit is the fast loop with KDGHWCLK ioctls. It seems
the kernel gets confused by those on Amigas with A2000 RTCs
and simply hangs after some time. Inserting a nanosleep helps." */
/* Christian T. Steigies: 1 instead of 1000000 is still sufficient
to keep the machine from freezing. */
#ifdef HAVE_nanosleep
struct timespec sleep = { 0, 1 };
nanosleep( &sleep, NULL );
#else
usleep(1);
#endif
if (i++ >= 1000000) {
fprintf(stderr, _("Timed out waiting for time change.\n"));
return 2;

View file

@ -1,31 +0,0 @@
# 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)

View file

@ -1,727 +0,0 @@
/**************************************************************************
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 <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#if defined(__i386__) || defined(__alpha__)
#include <asm/io.h> /* 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 <tm> 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;
}

View file

@ -1,599 +0,0 @@
.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.

File diff suppressed because it is too large Load diff

View file

@ -1,139 +0,0 @@
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
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);

View file

@ -1,219 +0,0 @@
/**************************************************************************
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 <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#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 <tm>
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 <new_broken_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;
}

View file

@ -1,425 +0,0 @@
/**************************************************************************
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 <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "hwclock.h"
/*
Get defines for rtc stuff.
Getting the rtc defines is nontrivial. The obvious way is by
including <linux/mc146818rtc.h> but that again includes <asm/io.h>
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 <asm/rtc.h> 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 <asm/rtc.h>
#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 <linux/version.h>
/* 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 <linux/kd.h>
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 <tm>
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 <new_broken_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;
}
}

View file

@ -1,467 +0,0 @@
/* $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 <sverrehu@ifi.uio.no>
*
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include "shhopt.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;
}
}
}

View file

@ -1,33 +0,0 @@
/* $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

View file

@ -1,120 +0,0 @@
/**************************************************************************
This is a component of the hwclock program.
This file contains the code for various basic utility routines
needed by the other modules.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#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 <increment> seconds after
the time <addend>. Of course, <increment> 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);
}

149
configure vendored
View file

@ -6,7 +6,6 @@
# 1. For mount/nfsmount.c: is inet_aton() available?
# 2. For fdisk/fdisksunlabel.c: is there a <scsi/scsi.h>?
# For fdisk/fdisk.c: is there a <linux/blkpg.h>?
# 3. For sys-utils/ipcs.c: do we need __KERNEL__ and <linux/linkage.h>?
# 4. For sys-utils/cytune.c: do we need <linux/tqueue.h>?
# 5. For sys-utils/kbd_rate.c: does <linux/kd.h> exist?
# 6. For cfdisk, setterm, more, ul: do we have ncurses? How installed?
@ -19,7 +18,22 @@
# 12. For cal.c: do we have <langinfo.h>?
# 13. For err.c: do we have __progname?
# 14. For script.c: do we have <pty.h> and openpty()?
# 15. For lib/widechar.h: do we have wide character support?
# 16. For clock/kd.c: do we have nanosleep()?
rm -f make_include defines.h
VERSION=`cat VERSION`
echo
echo configuring util-linux-$VERSION
echo
echo "VERSION=$VERSION" > make_include
echo '#define UTIL_LINUX_VERSION "'$VERSION'"' > defines.h
echo '#define util_linux_version "util-linux-'$VERSION'"' >> defines.h
echo >> defines.h
if test -z "$CC"
then
if test "$RANDOM" = "$RANDOM"; then
# Plain old Bourne shell.
echo checking for gcc
@ -29,6 +43,10 @@ else
echo checking for gcc
test -z "$CC" && type gcc && CC="gcc -O"
fi
else
echo "Using CC=\"$CC\""
echo
fi
CC=${CC-cc}
CFLAGS=${CFLAGS-"-O"}
@ -36,8 +54,10 @@ 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'
eval COMPILE='"'$compile'"'
export COMPILE
rm -f make_include defines.h conftest.c conftest
rm -f conftest.c conftest
#
# 1. For mount/nfsmount.c: is inet_aton() available?
@ -84,35 +104,9 @@ rm -f conftest conftest.c
#
# 2A. For fdisk/fdisk.c: is <linux/blkpg.h> available?
#
echo "
#include <linux/blkpg.h>
main(){ exit(0); }
" > conftest.c
eval $compile
if test -s conftest && ./conftest 2>/dev/null; then
if ./testincl "linux/blkpg.h"; then
echo "#define HAVE_blkpg_h" >> defines.h
echo "You have <linux/blkpg.h>"
else
echo "You don't have <linux/blkpg.h>"
fi
rm -f conftest conftest.c
#
# 3. ipcs.c includes <sys/shm.h> and family
# Do we need __KERNEL__ and asmlinkage for SHM_DEST?
#
echo "
#include <sys/shm.h>
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 <linux/linkage.h>"
else
echo "#define NEED_linkage_h" >> defines.h
echo "You need <linux/linkage.h>"
fi
rm -f conftest conftest.c
#
# 4. cytune.c may need struct tq_struct
@ -134,29 +128,22 @@ rm -f conftest conftest.c
#
# 5. Does <linux/kd.h> exist?
#
echo "
#include <linux/kd.h>
main(){ exit(0); }
" > conftest.c
eval $compile
if test -s conftest && ./conftest 2>/dev/null; then
if ./testincl "linux/kd.h"; then
echo "#define HAVE_kd_h" >> defines.h
echo "You have <linux/kd.h>"
else
echo "You don't have <linux/kd.h>"
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
if ! ./testincl "term.h"; then
have_ncurses=0
elif ./testincl -q "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 <ncurses/curses.h>."
elif [ -f /usr/include/ncurses.h ]; then
elif ./testincl -q "ncurses.h"; then
echo "HAVE_NCURSES=yes" >> make_include
echo "CURSESFLAGS=-DNCH=1" >> make_include
echo "You have ncurses. Using <ncurses.h>."
@ -164,7 +151,7 @@ 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
elif ./testincl -q "curses.h"; then
test_curses_h=1
else
have_ncurses=0
@ -214,8 +201,12 @@ if test -s conftest && ./conftest 2>/dev/null; then
echo "You have termcap"
else
echo "HAVE_TERMCAP=no" >> make_include
if [ $have_ncurses = 0 ]; then
echo "You don't have termcap - I will not make more."
else
echo "You don't have termcap"
fi
fi
rm -f conftest conftest.c
#
@ -253,18 +244,9 @@ fi
#
# 9. For lib/nls.h: do we have <locale.h>?
#
echo "
#include <locale.h>
main(){ exit(0); }
" > conftest.c
eval $compile
if test -s conftest && ./conftest 2>/dev/null; then
if ./testincl "locale.h"; then
echo "#define HAVE_locale_h" >> defines.h
echo "You have <locale.h>"
else
echo "You don't have <locale.h>"
fi
rm -f conftest conftest.c
#
@ -284,7 +266,7 @@ if test -s conftest && ./conftest 2>/dev/null; then
echo "You have <libintl.h> and gettext()"
echo '#define ENABLE_NLS' >> defines.h
echo "Assuming that you want to enable NLS support."
echo "(Otherwise, edit defines.h)"
echo "(Otherwise, edit defines.h and remove the line with ENABLE_NLS)"
ENABLE_NLS=yes
else
echo "You don't have <libintl.h>"
@ -311,18 +293,9 @@ fi
#
# 12. For cal.c: do we have <langinfo.h>?
#
echo "
#include <langinfo.h>
main(){ exit(0); }
" > conftest.c
eval $compile
if test -s conftest && ./conftest 2>/dev/null; then
if ./testincl "langinfo.h"; then
echo "#define HAVE_langinfo_h" >> defines.h
echo "You have <langinfo.h>"
else
echo "You don't have <langinfo.h>"
fi
rm -f conftest conftest.c
#
@ -343,7 +316,6 @@ else
fi
rm -f conftest conftest.c
#
# 14. For script.c: do we have <pty.h> and openpty()?
#
@ -360,3 +332,52 @@ else
echo "You don't have <pty.h> and openpty()"
fi
rm -f conftest conftest.c
#
# 15. For lib/widechar.h: do we have wide character support?
# [Do we have the headers <wchar.h>, <wctype.h>, the types wchar_t, wint_t
# and the fgetwc, fputwc, WEOF functions/macros?]
#
echo "
#include <wchar.h>
#include <wctype.h>
#include <stdio.h>
int main () {
wchar_t wc;
wint_t w;
w = fgetwc(stdin);
if (w == WEOF) exit(1);
wc = w;
fputwc(wc,stdout);
exit(0);
}
" > conftest.c
eval $compile
if test -s conftest && ./conftest < conftest.c > /dev/null 2>/dev/null; then
echo "#define ENABLE_WIDECHAR" >> defines.h
echo "You have wide character support"
else
echo "You don't have wide character support"
fi
rm -f conftest conftest.c
#
# 16. For clock/kd.c: do we have nanosleep?
#
echo "
#include <time.h>
int main () {
struct timespec sleep = { 0, 1 };
nanosleep( &sleep, NULL );
exit(0);
}
" > conftest.c
eval $compile
if test -s conftest && ./conftest 2>/dev/null; then
echo "#define HAVE_nanosleep" >> defines.h
echo "You have nanosleep()"
else
echo "You don't have nanosleep()"
fi
rm -f conftest conftest.c

View file

@ -1,49 +1,53 @@
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
# Revised: Fri Oct 6 21:02:21 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
include ../make_include
include ../MCONFIG
# Where to put man pages?
MAN8= fdformat.8 mkswap.8 setfdprm.8
MAN8= fdformat.8 mkfs.8 mkswap.8
# Where to put binaries?
# See the "install" rule for the links. . .
SBIN= mkfs mkswap
SBIN= mkfs mkswap blockdev
USRBIN= fdformat setfdprm
USRBIN= fdformat
ETC= fdprm
ifneq "$(CPU)" "sparc"
# fsck and mkfs will compile, but there is no kernel support on sparc
MAN8:=$(MAN8) fsck.minix.8 mkfs.8 mkfs.minix.8
SBIN:=$(SBIN) fsck.minix mkfs.minix
MAN8:=$(MAN8) fsck.minix.8 mkfs.minix.8 mkfs.bfs.8
SBIN:=$(SBIN) fsck.minix mkfs.minix mkfs.bfs
endif
# Where to put datebase files?
ifneq "$(HAVE_FDUTILS)" "yes"
USRBIN:=$(USRBIN) setfdprm
MAN8:=$(MAN8) setfdprm.8
endif
# raw.c does not compile on 2.2.*.
# find out later where it does and add tests to config
ifeq "$(ADD_RAW)" "yes"
USRBIN:=$(USRBIN) raw
MAN8:=$(MAN8) raw.8
endif
all: $(SBIN) $(USRBIN)
fdformat: fdformat.o
fsck.minix: fsck.minix.o
fsck.minix.o: fsck.minix.c bitops.h
mkfs: mkfs.o
mkfs.minix: mkfs.minix.o
mkfs.minix.o: mkfs.minix.c bitops.h
mkswap: mkswap.o
setfdprm: setfdprm.o
fsck.minix.o mkfs.minix.o: bitops.h
install: all
$(INSTALLDIR) $(SBINDIR) $(USRBINDIR) $(ETCDIR)
$(INSTALLBIN) $(SBIN) $(SBINDIR)
$(INSTALLBIN) $(USRBIN) $(USRBINDIR)
ifneq "$(HAVE_FDUTILS)" "yes"
$(INSTALLDAT) $(ETC) $(ETCDIR)
endif
$(INSTALLDIR) $(MAN8DIR)
$(INSTALLMAN) $(MAN8) $(MAN8DIR)

220
disk-utils/blockdev.c Normal file
View file

@ -0,0 +1,220 @@
/*
* blockdev.c --- Do various simple block device ioctls from the command line
* aeb, 991028
*/
#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include "nls.h"
const char *progname;
struct bdc {
char *name;
char *iocname;
long ioc;
int argtype;
#define ARGNONE 0
#define ARGINTA 1
#define ARGINTP 2
#define ARGINTG 3
#define ARGLINTG 4
long argval;
char *argname;
char *help;
} bdcms[] = {
#ifdef BLKROSET
{ "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") },
{ "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") },
#endif
#ifdef BLKROGET
{ "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") },
#endif
#ifdef BLKSSZGET
{ "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") },
#endif
#ifdef BLKGETSIZE
{ "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLINTG, -1, NULL, N_("get size") },
#endif
#ifdef BLKRASET
{ "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") },
#endif
#ifdef BLKRAGET
{ "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") },
#endif
#ifdef BLKFLSBUF
{ "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") },
#endif
#ifdef BLKRRPART
{ "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL,
N_("reread partition table") },
#endif
};
#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
static void
usage(void) {
int i;
fprintf(stderr, _("Usage: %s [-V] [-v|-q] commands devices\n"), progname);
fprintf(stderr, _("Available commands:\n"));
for (i = 0; i < SIZE(bdcms); i++) {
fprintf(stderr, "\t%s", bdcms[i].name);
if (bdcms[i].argname)
fprintf(stderr, " %s", bdcms[i].argname);
if (bdcms[i].help)
fprintf(stderr, "\t(%s)", _(bdcms[i].help));
fprintf(stderr, "\n");
}
exit(1);
}
int
find_cmd(char *s) {
int j;
for (j = 0; j < SIZE(bdcms); j++)
if (!strcmp(s, bdcms[j].name))
return j;
return -1;
}
void do_commands(int fd, char **argv, int d);
int
main(int argc, char **argv) {
int fd, d, j, k;
char *p;
/* egcs-2.91.66 is buggy and says:
blockdev.c:93: warning: `d' might be used uninitialized */
d = 0;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc < 2)
usage();
/* -V not together with commands */
if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
printf("%s from %s\n", progname, util_linux_version);
exit(0);
}
/* do each of the commands on each of the devices */
/* devices start after last command */
for (d = 1; d < argc; d++) {
j = find_cmd(argv[d]);
if (j >= 0) {
if (bdcms[j].argtype == ARGINTA)
d++;
continue;
}
if (!strcmp(argv[d], "--")) {
d++;
break;
}
if (argv[d][0] != '-')
break;
}
if (d >= argc)
usage();
for (k = d; k < argc; k++) {
fd = open(argv[k], O_RDONLY, 0);
if (fd < 0) {
perror(argv[k]);
exit(1);
}
do_commands(fd, argv, d);
}
return 0;
}
void
do_commands(int fd, char **argv, int d) {
int res, i, j;
int iarg;
long larg;
int verbose = 0;
for (i = 1; i < d; i++) {
if (!strcmp(argv[i], "-v")) {
verbose = 1;
continue;
}
if (!strcmp(argv[i], "-q")) {
verbose = 0;
continue;
}
j = find_cmd(argv[i]);
if (j == -1) {
fprintf(stderr, _("%s: Unknown command: %s\n"), progname, argv[i]);
usage();
}
switch(bdcms[j].argtype) {
default:
case ARGNONE:
res = ioctl(fd, bdcms[j].ioc, 0);
break;
case ARGINTA:
if (i == d-1) {
fprintf(stderr, _("%s requires an argument\n"),
bdcms[j].name);
usage();
}
iarg = atoi(argv[++i]);
res = ioctl(fd, bdcms[j].ioc, iarg);
break;
case ARGINTP:
case ARGINTG:
iarg = bdcms[j].argval;
res = ioctl(fd, bdcms[j].ioc, &iarg);
break;
case ARGLINTG:
larg = bdcms[j].argval;
res = ioctl(fd, bdcms[j].ioc, &larg);
break;
}
if (res == -1) {
perror(bdcms[j].iocname);
if (verbose)
printf("%s failed.\n", _(bdcms[j].help));
exit(1);
}
switch(bdcms[j].argtype) {
case ARGINTG:
if (verbose)
printf("%s: %d\n", _(bdcms[j].help), iarg);
else
printf("%d\n", iarg);
break;
case ARGLINTG:
if (verbose)
printf("%s: %ld\n", _(bdcms[j].help), larg);
else
printf("%ld\n", larg);
break;
default:
if (verbose)
printf("%s succeeded.\n", _(bdcms[j].help));
break;
}
}
}

View file

@ -101,22 +101,31 @@ static void usage(char *name)
int main(int argc,char **argv)
{
int verify;
char *name;
struct stat st;
char *progname, *p;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
name = argv[0];
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), progname, util_linux_version);
exit(0);
}
verify = 1;
if (argc > 1 && argv[1][0] == '-') {
if (argv[1][1] != 'n') usage(name);
if (argv[1][1] != 'n') usage(progname);
verify = 0;
argc--;
argv++;
}
if (argc != 2) usage(name);
if (argc != 2) usage(progname);
if (stat(argv[1],&st) < 0) PERROR(argv[1]);
if (!S_ISBLK(st.st_mode) || MAJOR(st.st_rdev) != FLOPPY_MAJOR) {
fprintf(stderr,_("%s: not a floppy device\n"),argv[1]);
@ -127,7 +136,8 @@ int main(int argc,char **argv)
if (ioctl(ctrl,FDGETPRM,(long) &param) < 0)
PERROR(_("Could not determine current format type"));
printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"),
param.head ? _("Double") : _("Single"),param.track,param.sect,param.size >> 1);
param.head ? _("Double") : _("Single"),
param.track, param.sect,param.size >> 1);
format_disk(argv[1]);
if (verify) verify_disk(argv[1]);
return 0;

View file

@ -98,7 +98,6 @@
#include <linux/fs.h>
#include <linux/minix_fs.h>
#include "../version.h"
#include "nls.h"
#ifdef MINIX2_SUPER_MAGIC2
@ -125,7 +124,6 @@
#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
static char * program_name = "fsck.minix";
static char * program_version = "1.2 - 11/11/96";
static char * device_name = NULL;
static int IN;
static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0,
@ -185,17 +183,25 @@ void recursive_check2(unsigned int ino);
#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1)
#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1)
void fatal_error(const char *, int) __attribute__ ((noreturn));
void fatal_error(const char * fmt_string, int status)
void leave(int) __attribute__ ((noreturn));
void leave(int status)
{
fprintf(stderr,fmt_string,program_name,device_name);
if (termios_set)
tcsetattr(0, TCSANOW, &termios);
exit(status);
}
#define usage() fatal_error(_("Usage: %s [-larvsmf] /dev/name\n"),16)
#define die(str) fatal_error(_("%s: " str "\n"),8)
void usage(void) {
fprintf(stderr,
_("Usage: %s [-larvsmf] /dev/name\n"),
program_name);
leave(16);
}
void die(const char *str) {
fprintf(stderr, "%s: %s\n", program_name, str);
leave(8);
}
/*
* This simply goes through the file-name data and prints out the
@ -381,7 +387,7 @@ void write_block(unsigned int nr, char * addr)
return;
}
if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET))
die("seek failed in write_block");
die(_("seek failed in write_block"));
if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
printf(_("Write error: bad block in file '"));
print_current_name();
@ -502,9 +508,9 @@ void write_super_block(void)
Super.s_state &= ~MINIX_ERROR_FS;
if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
die("seek failed in write_super_block");
die(_("seek failed in write_super_block"));
if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
die("unable to write super-block");
die(_("unable to write super-block"));
return;
}
@ -514,11 +520,11 @@ void write_tables(void)
write_super_block();
if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE))
die("Unable to write inode map");
die(_("Unable to write inode map"));
if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE))
die("Unable to write zone map");
die(_("Unable to write zone map"));
if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE))
die("Unable to write inodes");
die(_("Unable to write inodes"));
}
void get_dirsize (void)
@ -547,9 +553,9 @@ void get_dirsize (void)
void read_superblock(void)
{
if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
die("seek failed");
die(_("seek failed"));
if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
die("unable to read super block");
die(_("unable to read super block"));
if (MAGIC == MINIX_SUPER_MAGIC) {
namelen = 14;
dirsize = 16;
@ -569,20 +575,20 @@ void read_superblock(void)
version2 = 1;
#endif
} else
die("bad magic number in super-block");
die(_("bad magic number in super-block"));
if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
die("Only 1k blocks/zones supported");
die(_("Only 1k blocks/zones supported"));
if (IMAPS * BLOCK_SIZE * 8 < INODES + 1)
die("bad s_imap_blocks field in super-block");
die(_("bad s_imap_blocks field in super-block"));
if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1)
die("bad s_zmap_blocks field in super-block");
die(_("bad s_zmap_blocks field in super-block"));
}
void read_tables(void)
{
inode_map = malloc(IMAPS * BLOCK_SIZE);
if (!inode_map)
die("Unable to allocate buffer for inode map");
die(_("Unable to allocate buffer for inode map"));
zone_map = malloc(ZMAPS * BLOCK_SIZE);
if (!inode_map)
die("Unable to allocate buffer for zone map");
@ -590,19 +596,19 @@ void read_tables(void)
memset(zone_map,0,sizeof(zone_map));
inode_buffer = malloc(INODE_BUFFER_SIZE);
if (!inode_buffer)
die("Unable to allocate buffer for inodes");
die(_("Unable to allocate buffer for inodes"));
inode_count = malloc(INODES + 1);
if (!inode_count)
die("Unable to allocate buffer for inode count");
die(_("Unable to allocate buffer for inode count"));
zone_count = malloc(ZONES);
if (!zone_count)
die("Unable to allocate buffer for zone count");
die(_("Unable to allocate buffer for zone count"));
if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE))
die("Unable to read inode map");
die(_("Unable to read inode map"));
if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE))
die("Unable to read zone map");
die(_("Unable to read zone map"));
if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE))
die("Unable to read inodes");
die(_("Unable to read inodes"));
if (NORM_FIRSTZONE != FIRSTZONE) {
printf(_("Warning: Firstzone != Norm_firstzone\n"));
errors_uncorrected = 1;
@ -723,7 +729,7 @@ void check_root(void)
struct minix_inode * inode = Inode + ROOT_INO;
if (!inode || !S_ISDIR(inode->i_mode))
die("root inode isn't a directory");
die(_("root inode isn't a directory"));
}
#ifdef HAVE_MINIX2
@ -1065,7 +1071,7 @@ void recursive_check(unsigned int ino)
dir = Inode + ino;
if (!S_ISDIR(dir->i_mode))
die("internal error");
die(_("internal error"));
if (dir->i_size < 2 * dirsize) {
print_current_name();
printf(_(": bad directory: size<32"));
@ -1100,7 +1106,7 @@ int bad_zone(int i)
char buffer[1024];
if (BLOCK_SIZE*i != lseek(IN, BLOCK_SIZE*i, SEEK_SET))
die("seek failed in bad_zone");
die(_("seek failed in bad_zone"));
return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
}
@ -1234,19 +1240,27 @@ int main(int argc, char ** argv)
struct termios tmp;
int count;
int retcode = 0;
char *p;
program_name = (argc && *argv) ? argv[0] : "fsck.minix";
if ((p = strrchr(program_name, '/')) != NULL)
program_name = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), program_name, util_linux_version);
exit(0);
}
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 v2 inode size");
die(_("bad v2 inode size"));
#endif
while (argc-- > 1) {
argv++;
@ -1272,11 +1286,11 @@ int main(int argc, char ** argv)
check_mount(); /* trying to check a mounted filesystem? */
if (repair && !automatic) {
if (!isatty(0) || !isatty(1))
die("need terminal for interactive repairs");
die(_("need terminal for interactive repairs"));
}
IN = open(device_name,repair?O_RDWR:O_RDONLY);
if (IN < 0)
die("unable to open '%s'");
die(_("unable to open '%s'"));
for (count=0 ; count<3 ; count++)
sync();
read_superblock();
@ -1287,8 +1301,6 @@ int main(int argc, char ** argv)
* flags and whether or not the -f switch was specified on the
* command line.
*/
printf("%s, %s / %s\n", program_name, program_version,
util_linux_version);
if ( !(Super.s_state & MINIX_ERROR_FS) &&
(Super.s_state & MINIX_VALID_FS) &&
!force ) {

48
disk-utils/mkfs.bfs.8 Normal file
View file

@ -0,0 +1,48 @@
.\" Copyright 1999 Andries E. Brouwer (aeb@cwi.nl)
.\" May be freely distributed.
.TH MKFS.BFS 8 "12 Sept 1999" "Util-linux 2.9x" "Linux System Administrator's Manual"
.SH NAME
mkfs.bfs \- make an SCO bfs filesystem
.SH SYNOPSIS
.BR "mkfs.bfs [ \-N"
nr-of-inodes
.B ] [ \-V
volume-name
.B ] [ \-F
fsname
.B ]
device
.B [
size-in-blocks
.B ]
.SH DESCRIPTION
.B mkfs.bfs
creates an SCO bfs file-system on a block device
(usually a disk partition or a file accessed via the loop device).
The
.I size-in-blocks
parameter is the desired size of the file system, in blocks.
If nothing is specified, the entire partition will be used.
.SH OPTIONS
.TP
.B \-N
Specify the desired number of inodes (at most 512).
If nothing is specified some default number in the range 48-512 is picked
depending on the size of the partition.
.TP
.BI \-V " volume-label"
Specify the volume label. I have no idea if/where this is used.
.TP
.BI \-F " fsname"
Specify the fsname. I have no idea if/where this is used.
.TP
.B \-v
Be verbose.
.SH "EXIT CODES"
The exit code returned by
.B mkfs.bfs
is 0 when all went well, and 1 when something went wrong.
.SH "SEE ALSO"
.BR mkfs (8).

284
disk-utils/mkfs.bfs.c Normal file
View file

@ -0,0 +1,284 @@
/*
* mkfs.bfs - Create SCO BFS filesystem - aeb, 1999-09-07
*
* Usage: mkfs.bfs [-N nr-of-inodes] [-V volume-name] [-F fsname] device
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <linux/fs.h> /* for BLKGETSIZE */
#include "../defines.h" /* for util_linux_version */
#define BFS_ROOT_INO 2
#define BFS_NAMELEN 14
#define BFS_BLOCKSIZE 512
#define BFS_SUPER_MAGIC 0x1badface
/* superblock - 512 bytes */
struct bfssb {
unsigned int s_magic;
unsigned int s_start; /* byte offset of start of data */
unsigned int s_end; /* sizeof(slice)-1 */
/* for recovery during compaction */
int s_from, s_to; /* src and dest block of current transfer */
int s_backup_from, s_backup_to;
/* labels - may well contain garbage */
char s_fsname[6];
char s_volume[6];
char s_pad[472];
};
/* inode - 64 bytes */
struct bfsi {
unsigned short i_ino;
unsigned char i_pad1[2];
unsigned long i_first_block;
unsigned long i_last_block;
unsigned long i_bytes_to_end;
unsigned long i_type; /* 1: file, 2: the unique dir */
unsigned long i_mode;
unsigned long i_uid, i_gid;
unsigned long i_nlinks;
unsigned long i_atime, i_mtime, i_ctime;
unsigned char i_pad2[16];
};
#define BFS_DIR_TYPE 2
/* directory entry - 16 bytes */
struct bfsde {
unsigned short d_ino;
char d_name[BFS_NAMELEN];
};
static char *progname;
static void
fatal(char *s, ...) {
va_list p;
va_start(p, s);
fflush(stdout);
fprintf(stderr, "\n%s: ", progname);
vfprintf(stderr, s, p);
va_end(p);
fprintf(stderr, "\n");
exit(1);
}
static void
usage(void) {
fprintf(stderr,
"Usage: %s [-v] [-N nr-of-inodes] [-V volume-name]\n"
" [-F fsname] device [block-count]\n",
progname);
exit(1);
}
int
main(int argc, char *argv[]) {
char *device, *volume, *fsname;
int inodes;
unsigned long total_blocks, ino_bytes, ino_blocks, data_blocks;
unsigned long user_specified_total_blocks = 0;
int verbose = 0;
int fd;
struct bfssb sb;
struct bfsi ri;
struct bfsde de;
struct stat statbuf;
time_t now;
int c, i, len;
char *p;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
if (argc < 2)
usage();
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf("%s from %s\n", progname, util_linux_version);
exit(0);
}
volume = fsname = " "; /* is there a default? */
inodes = 0;
while (EOF != (c = getopt(argc, argv, "vF:N:V:cl:"))) {
switch (c) {
case 'N':
inodes = atol(optarg);
break;
case 'V':
len = strlen(optarg);
if (len <= 0 || len > 6)
fatal("volume name too long");
volume = strdup(optarg);
break;
case 'F':
len = strlen(optarg);
if (len <= 0 || len > 6)
fatal("fsname name too long");
fsname = strdup(optarg);
break;
case 'v':
verbose = 1;
break;
/* when called via mkfs we may get options c,l,v */
case 'c':
case 'l':
break;
default:
usage();
}
}
if (optind == argc)
usage();
device = argv[optind++];
if (stat(device, &statbuf) == -1) {
perror(device);
fatal("cannot stat device %s", device);
}
if (!S_ISBLK(statbuf.st_mode))
fatal("%s is not a block special device", device);
fd = open(device, O_RDWR);
if (fd == -1) {
perror(device);
fatal("cannot open %s", device);
}
if (optind == argc-1)
user_specified_total_blocks = atoi(argv[optind]);
else if (optind != argc)
usage();
if (ioctl(fd, BLKGETSIZE, &total_blocks) == -1) {
if (!user_specified_total_blocks) {
perror("BLKGETSIZE");
fatal("cannot get size of %s", device);
}
total_blocks = user_specified_total_blocks;
} else if (user_specified_total_blocks) {
if (user_specified_total_blocks > total_blocks)
fatal("blocks argument too large, max is %d",
total_blocks);
total_blocks = user_specified_total_blocks;
}
if (!inodes) {
/* pick some reasonable default */
inodes = 8*(total_blocks/800);
if (inodes < 48)
inodes = 48;
if (inodes > 512)
inodes = 512;
} else {
/* believe the user */
if (inodes > 512)
fatal("too many inodes - max is 512");
}
ino_bytes = inodes * sizeof(struct bfsi);
ino_blocks = (ino_bytes + BFS_BLOCKSIZE - 1) / BFS_BLOCKSIZE;
data_blocks = total_blocks - ino_blocks - 1;
/* mimic the behaviour of SCO's mkfs - maybe this limit is needed */
if (data_blocks < 32)
fatal("not enough space, need at least %d blocks",
ino_blocks + 33);
memset(&sb, 0, sizeof(sb));
sb.s_magic = BFS_SUPER_MAGIC;
sb.s_start = ino_bytes + sizeof(struct bfssb);
sb.s_end = total_blocks * BFS_BLOCKSIZE - 1;
sb.s_from = sb.s_to = sb.s_backup_from = sb.s_backup_to = -1;
memcpy(sb.s_fsname, fsname, 6);
memcpy(sb.s_volume, volume, 6);
if (verbose) {
fprintf(stderr, "Device: %s\n", device);
fprintf(stderr, "Volume: <%-6s>\n", volume);
fprintf(stderr, "FSname: <%-6s>\n", fsname);
fprintf(stderr, "BlockSize: %d\n", BFS_BLOCKSIZE);
fprintf(stderr, "Inodes: %d (in %ld block%s)\n",
inodes, ino_blocks, (ino_blocks==1) ? "" : "s");
fprintf(stderr, "Blocks: %ld\n", total_blocks);
fprintf(stderr, "Inode end: %d, Data end: %d\n",
sb.s_start-1, sb.s_end);
}
if (write(fd, &sb, sizeof(sb)) != sizeof(sb))
fatal("error writing superblock");
memset(&ri, 0, sizeof(ri));
ri.i_ino = BFS_ROOT_INO;
ri.i_first_block = 1 + ino_blocks;
ri.i_last_block = ri.i_first_block +
(inodes * sizeof(de) - 1) / BFS_BLOCKSIZE;
ri.i_bytes_to_end = ri.i_first_block * BFS_BLOCKSIZE
+ 2 * sizeof(struct bfsde) - 1;
ri.i_type = BFS_DIR_TYPE;
ri.i_mode = S_IFDIR | 0755; /* or just 0755 */
ri.i_uid = 0;
ri.i_gid = 1; /* random */
ri.i_nlinks = 2;
time(&now);
ri.i_atime = now;
ri.i_mtime = now;
ri.i_ctime = now;
if (write(fd, &ri, sizeof(ri)) != sizeof(ri))
fatal("error writing root inode");
memset(&ri, 0, sizeof(ri));
for (i=1; i<inodes; i++)
if (write(fd, &ri, sizeof(ri)) != sizeof(ri))
fatal("error writing inode");
if (lseek(fd, (1 + ino_blocks)*BFS_BLOCKSIZE, SEEK_SET) == -1)
fatal("seek error");
memset(&de, 0, sizeof(de));
de.d_ino = BFS_ROOT_INO;
memcpy(de.d_name, ".", 1);
if (write(fd, &de, sizeof(de)) != sizeof(de))
fatal("error writing . entry");
memcpy(de.d_name, "..", 2);
if (write(fd, &de, sizeof(de)) != sizeof(de))
fatal("error writing .. entry");
if (close(fd) == -1) {
perror(device);
fatal("error closing %s", device);
}
return 0;
}

View file

@ -24,7 +24,6 @@
#include <limits.h>
#include "nls.h"
#include "../version.h"
#define VERSION UTIL_LINUX_VERSION
#ifndef DEFAULT_FSTYPE
@ -41,11 +40,22 @@ int main(int argc, char *argv[])
char *fstype = NULL;
int i, more = 0, verbose = 0;
char *oldpath, *newpath;
char *program_name, *p;
program_name = argv[0];
if ((p = strrchr(program_name, '/')) != NULL)
program_name = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), program_name, util_linux_version);
exit(0);
}
/* Check commandline options. */
opterr = 0;
while ((more == 0) && ((i = getopt(argc, argv, "Vt:")) != EOF))
@ -86,7 +96,7 @@ int main(int argc, char *argv[])
argv[--optind] = progname;
if (verbose) {
puts(_("mkfs version " VERSION " (" __DATE__ ")"));
printf(_("mkfs version %s (%s)\n"), VERSION, __DATE__);
i = optind;
while (argv[i])
printf("%s ", argv[i++]);

View file

@ -1,11 +1,10 @@
.\" Copyright 1992, 1993, 1994 Rickard E. Faith (faith@cs.unc.edu)
.\" May be freely distributed.
.\" " for emacs hilit19 mode
.TH MKFS 8 "2 July 1996" "Util-linux 2.6" "Linux System Administrator's Manual"
.TH MKFS.MINIX 8 "2 July 1996" "Util-linux 2.6" "Linux System Administrator's Manual"
.SH NAME
mkfs \- make a Linux MINIX filesystem
mkfs.minix \- make a Linux MINIX filesystem
.SH SYNOPSIS
.BR "mkfs [ \-c | \-l filename ] [ \-n"
.BR "mkfs.minix [ \-c | \-l filename ] [ \-n"
namelength
.B ] [ \-i
inodecount
@ -15,7 +14,7 @@ device
size-in-blocks
.B ]
.SH DESCRIPTION
.B mkfs
.B mkfs.minix
creates a Linux MINIX file-system on a device (usually a disk partition).
The
@ -33,14 +32,11 @@ is usually of the following form:
The
.I size-in-blocks
parameter is the desired size of the file system, in blocks. This
information can be determined from the
.BR fdisk (8)
or
.BR cfdisk (8)
program. If omitted it will be determined automaticaly. Only block
counts strictly greater than 10 and strictly less than 65536 are
allowed.
parameter is the desired size of the file system, in blocks.
It is present only for backwards compatibility.
If omitted the size will be determined automatically.
Only block counts strictly greater than 10 and strictly less than
65536 are allowed.
.SH OPTIONS
.TP
.B \-c
@ -50,7 +46,7 @@ are found, the count is printed.
.BI \-n " namelength"
Specify the maximum length of filenames.
Currently, the only allowable values are 14 and 30.
.B 30 is the default.
The default is 30.
.TP
.BI \-i " inodecount"
Specify the number of inodes for the filesystem.
@ -76,24 +72,4 @@ Usage or syntax error
.SH "SEE ALSO"
.BR mkfs (8),
.BR fsck (8),
.BR mke2fs (8),
.BR e2fsck (8),
.BR reboot (8)
.\" .SH AUTHORS
.\" Linus Torvalds (torvalds@cs.helsinki.fi).
.\" .br
.\" Error code values by Rik Faith (faith@cs.unc.edu)
.\" .br
.\" Inode request feature by Scott Heavner (sdh@po.cwru.edu)
.\" .br
.\" Support for the file system valid flag by Dr. Wettstein
.\" (greg%wind.uucp@plains.nodak.edu)
.\" .br
.\" Check to prevent mkfs of mounted filesystem and boot sector clearing
.\" by Daniel Quinlan (quinlan@yggdrasil.com)
.\" .br
.\" Minix v2 support by Andreas Schwab
.\" (schwab@issan.informatik.uni-dortmund.de), updated by Nicolai
.\" Langfeldt (janl@math.uio.no)
.\" .br
.\" Portability patch by Russell King.

View file

@ -76,7 +76,6 @@
#include <linux/minix_fs.h>
#include "nls.h"
#include "../version.h"
#ifdef MINIX2_SUPER_MAGIC2
#define HAVE_MINIX2 1
@ -489,6 +488,7 @@ void setup_tables(void)
ZONESIZE = 0;
MAXSIZE = version2 ? 0x7fffffff : (7+512+512*512)*1024;
ZONES = BLOCKS;
/* some magic nrs: 1 inode / 3 blocks */
if ( req_nr_inodes == 0 )
inodes = BLOCKS/3;
@ -507,9 +507,13 @@ void setup_tables(void)
inodes = 65535;
INODES = inodes;
IMAPS = UPPER(INODES + 1,BITS_PER_BLOCK);
ZMAPS = 0;
while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK))
ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK);
ZMAPS = UPPER(BLOCKS - (1+IMAPS+INODE_BLOCKS), BITS_PER_BLOCK+1);
/* The old code here
* ZMAPS = 0;
* while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK))
* ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK);
* was no good, since it may loop. - aeb
*/
FIRSTZONE = NORM_FIRSTZONE;
inode_map = malloc(IMAPS * BLOCK_SIZE);
zone_map = malloc(ZMAPS * BLOCK_SIZE);
@ -630,9 +634,23 @@ int main(int argc, char ** argv)
char * tmp;
struct stat statbuf;
char * listfile = NULL;
char * p;
if (argc && *argv)
program_name = *argv;
if ((p = strrchr(program_name, '/')) != NULL)
program_name = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), program_name, util_linux_version);
exit(0);
}
if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
die(_("bad inode size"));
#ifdef HAVE_MINIX2

View file

@ -7,7 +7,7 @@
.SH NAME
mkswap \- set up a Linux swap area
.SH SYNOPSIS
.BI "mkswap [\-c] [\-v" N "] [\-f] " device " [" size "]"
.BI "mkswap [\-c] [\-v" N "] [\-f] [\-p " PSZ "] "device " [" size "]"
.SH DESCRIPTION
.B mkswap
sets up a Linux swap area on a device or in a file.
@ -30,6 +30,8 @@ but can also be a file.
The Linux kernel does not look at partition Id's, but
many installation scripts will assume that partitions
of hex type 82 (LINUX_SWAP) are meant to be swap partitions.
(Warning: Solaris also uses this type. Be careful not to kill
your Solaris partitions.)
The
.I size
@ -39,6 +41,18 @@ parameter is superfluous but retained for backwards compatibility.
will use the entire partition or file if it is omitted.
Specifying it is unwise - a typo may destroy your disk.)
The
.I PSZ
parameter specifies the page size to use. It is almost always
unnecessary (even unwise) to specify it, but certain old libc
versions lie about the page size, so it is possible that
.B mkswap
gets it wrong. The symptom is that a subsequent
.B swapon
fails because no swap signature is found. Typical values for
.I PSZ
are 4096 or 8192.
Linux knows about two styles of swap areas, old style and new style.
The last 10 bytes of the first page of the swap area distinguishes
them: old style has `SWAP_SPACE', new style has `SWAPSPACE2' as
@ -51,9 +65,9 @@ Also, the last 10 bytes hold the signature. So, if the page
size is S, an old style swap area can describe at most
8*(S-10)-1 pages used for swapping.
With S=4096 (as on i386), the useful area is at most 133890048 bytes
(almost 128 MB if you believe in 1 MB=2^20 bytes), and the rest is wasted.
(almost 128 MiB), and the rest is wasted.
On an alpha and sparc64, with S=8192, the useful area is at most
535560992 bytes (almost 512 MB with the same proviso).
535560992 bytes (almost 512 MiB).
The old setup wastes most of this bitmap page, because zero bits
denote bad blocks or blocks past the end of the swap space,
@ -63,12 +77,12 @@ to use a swap space with hundreds of bad blocks. (I would not even
use a swap space with 1 bad block.)
In the new style swap area this is precisely what is done.
The maximum useful size of a swap area now depends on the architecture.
It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
128GB on alpha and 3TB on sparc64.
It is roughly 2GiB on i386, PPC, m68k, ARM, 1GiB on sparc, 512MiB on mips,
128GiB on alpha and 3TiB on sparc64.
Note that before 2.1.117 the kernel allocated one byte for each page,
while it now allocates two bytes, so that taking a swap area of 2 GB
in use might require 2 MB of kernel memory.
while it now allocates two bytes, so that taking a swap area of 2 GiB
in use might require 2 MiB of kernel memory.
Presently, Linux allows 8 swap areas. The areas in use can be seen
in the file
@ -114,6 +128,9 @@ Without this option
will refuse to create a v0 swap on a device with a valid SPARC superblock,
as that probably means one is going to erase the partition table.
.TP
.BI "\-p " PSZ
Specify the page size to use.
.TP
.B \-v0
Create an old style swap area.
.TP

View file

@ -77,9 +77,20 @@ linux_version_code(void) {
/*
* The definition of the union swap_header uses the constant PAGE_SIZE.
* Unfortunately, on some architectures this depends on the hardware model,
* and can only be found at run time -- we use getpagesize().
* and can only be found at run time -- we use getpagesize(), so that
* we do not need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
*
* Even more unfortunately, getpagesize() does not always return
* the right information. For example, libc4 and libc5 do not use
* the system call but invent a value themselves
* (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC), and thus it may happen
* that e.g. on a sparc PAGE_SIZE=4096 and getpagesize() returns 8192.
* What to do? Let us allow the user to specify the pagesize explicitly.
*/
static int user_pagesize = 0;
static int kernel_pagesize; /* obtained via getpagesize(); */
static int defined_pagesize = 0; /* PAGE_SIZE, when that exists */
static int pagesize;
static int *signature_page;
@ -94,12 +105,31 @@ struct swap_header_v1 {
static void
init_signature_page() {
pagesize = getpagesize();
#ifdef PAGE_SIZE
if (pagesize != PAGE_SIZE)
fprintf(stderr, _("Assuming pages of size %d\n"), pagesize);
defined_pagesize = PAGE_SIZE;
#endif
kernel_pagesize = getpagesize();
pagesize = kernel_pagesize;
if (user_pagesize) {
if ((user_pagesize & (user_pagesize-1)) ||
user_pagesize < 1024) {
fprintf(stderr, _("Bad user-specified page size %d\n"),
user_pagesize);
exit(1);
}
pagesize = user_pagesize;
}
if (user_pagesize && user_pagesize != kernel_pagesize &&
user_pagesize != defined_pagesize)
fprintf(stderr, _("Using user-specified page size %d, "
"instead of the system values %d/%d\n"),
pagesize, kernel_pagesize, defined_pagesize);
else if (defined_pagesize && pagesize != defined_pagesize)
fprintf(stderr, _("Assuming pages of size %d (not %d)\n"),
pagesize, defined_pagesize);
signature_page = (int *) malloc(pagesize);
memset(signature_page,0,pagesize);
p = (struct swap_header_v1 *) signature_page;
@ -158,8 +188,8 @@ It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
static void bit_set (unsigned int *addr, unsigned int nr)
{
static void
bit_set (unsigned int *addr, unsigned int nr) {
unsigned int r, m;
addr += nr / (8 * sizeof(int));
@ -168,8 +198,8 @@ static void bit_set (unsigned int *addr, unsigned int nr)
*addr = r | m;
}
static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
{
static int
bit_test_and_clear (unsigned int *addr, unsigned int nr) {
unsigned int r, m;
addr += nr / (8 * sizeof(int));
@ -179,14 +209,19 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
return (r & m) != 0;
}
void fatal_error(const char * fmt_string)
{
fprintf(stderr,fmt_string,program_name,device_name);
void
usage(void) {
fprintf(stderr,
_("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n"),
program_name);
exit(1);
}
#define usage() fatal_error(_("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n"))
#define die(str) fatal_error(_("%s: " str "\n"))
void
die(const char *str) {
fprintf(stderr, "%s: %s\n", program_name, str);
exit(1);
}
void
page_ok(int page) {
@ -200,7 +235,7 @@ page_bad(int page) {
bit_test_and_clear(signature_page, page);
else {
if (badpages == MAX_BADPAGES)
die("too many bad pages");
die(_("too many bad pages"));
p->badpages[badpages] = page;
}
badpages++;
@ -214,7 +249,7 @@ check_blocks(void) {
buffer = malloc(pagesize);
if (!buffer)
die("Out of memory");
die(_("Out of memory"));
current_page = 0;
while (current_page < PAGES) {
if (!check) {
@ -223,7 +258,7 @@ check_blocks(void) {
}
if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
current_page*pagesize)
die("seek failed in check_blocks");
die(_("seek failed in check_blocks"));
if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
page_bad(current_page++);
continue;
@ -236,8 +271,8 @@ check_blocks(void) {
printf(_("%d bad pages\n"), badpages);
}
static long valid_offset (int fd, int offset)
{
static long
valid_offset (int fd, int offset) {
char ch;
if (lseek (fd, offset, 0) < 0)
@ -248,8 +283,7 @@ static long valid_offset (int fd, int offset)
}
static int
find_size (int fd)
{
find_size (int fd) {
unsigned int high, low;
low = 0;
@ -269,8 +303,7 @@ find_size (int fd)
/* return size in pages, to avoid integer overflow */
static long
get_size(const char *file)
{
get_size(const char *file) {
int fd;
long size;
@ -289,58 +322,85 @@ get_size(const char *file)
return size;
}
int main(int argc, char ** argv)
{
char * tmp;
int
isnzdigit(char c) {
return (c >= '1' && c <= '9');
}
int
main(int argc, char ** argv) {
struct stat statbuf;
int sz;
int i, sz;
int maxpages;
int goodpages;
int offset;
int force = 0;
char *block_count = 0;
char *pp;
program_name = (argc && *argv) ? argv[0] : "fsck.minix";
if ((pp = strrchr(program_name, '/')) != NULL)
program_name = pp+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), program_name, util_linux_version);
exit(0);
}
if (argc && *argv)
program_name = *argv;
init_signature_page(); /* get pagesize */
while (argc-- > 1) {
argv++;
if (argv[0][0] != '-') {
if (device_name) {
int blocks_per_page = pagesize/1024;
PAGES = strtol(argv[0],&tmp,0)/blocks_per_page;
if (*tmp)
usage();
} else
device_name = argv[0];
} else {
switch (argv[0][1]) {
for (i=1; i<argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'c':
check=1;
break;
case 'f':
force=1;
break;
case 'p':
pp = argv[i]+2;
if (!*pp && i+1 < argc)
pp = argv[++i];
if (isnzdigit(*pp))
user_pagesize=atoi(pp);
else
usage();
break;
case 'v':
version = atoi(argv[0]+2);
break;
default:
usage();
}
} else if (!device_name) {
device_name = argv[i];
} else if (!block_count) {
block_count = argv[i];
} else
usage();
}
}
init_signature_page(); /* get pagesize */
if (!device_name) {
fprintf(stderr,
_("%s: error: Nowhere to set up swap on?\n"),
program_name);
usage();
}
if (block_count) {
/* this silly user specified the number of blocks
explicitly */
char *tmp;
int blocks_per_page = pagesize/1024;
PAGES = strtol(block_count,&tmp,0)/blocks_per_page;
if (*tmp)
usage();
}
sz = get_size(device_name);
if (!PAGES) {
PAGES = sz;
@ -401,7 +461,7 @@ int main(int argc, char ** argv)
if (!S_ISBLK(statbuf.st_mode))
check=0;
else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
die("Will not try to make swapdevice on '%s'");
die(_("Will not try to make swapdevice on '%s'"));
#ifdef __sparc__
if (!force && version == 0) {
@ -410,7 +470,7 @@ int main(int argc, char ** argv)
unsigned short *q, sum;
if (read(DEV, buffer, 512) != 512)
die("fatal: first page unreadable");
die(_("fatal: first page unreadable"));
if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
q = (unsigned short *)(buffer + 510);
for (sum = 0; q >= (unsigned short *) buffer;)
@ -431,7 +491,7 @@ the -f option to force it.\n"),
if (version == 0 || check)
check_blocks();
if (version == 0 && !bit_test_and_clear(signature_page,0))
die("fatal: first page unreadable");
die(_("fatal: first page unreadable"));
if (version == 1) {
p->version = version;
p->last_page = PAGES-1;
@ -440,23 +500,23 @@ the -f option to force it.\n"),
goodpages = PAGES - badpages - 1;
if (goodpages <= 0)
die("Unable to set up swap-space: unreadable");
die(_("Unable to set up swap-space: unreadable"));
printf(_("Setting up swapspace version %d, size = %ld bytes\n"),
version, (long)(goodpages*pagesize));
write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
offset = ((version == 0) ? 0 : 1024);
if (lseek(DEV, offset, SEEK_SET) != offset)
die("unable to rewind swap-device");
die(_("unable to rewind swap-device"));
if (write(DEV,(char*)signature_page+offset, pagesize-offset)
!= pagesize-offset)
die("unable to write signature page");
die(_("unable to write signature page"));
/*
* A subsequent swapon() will fail if the signature
* is not actually on disk. (This is a kernel bug.)
*/
if (fsync(DEV))
die("fsync failed");
die(_("fsync failed"));
return 0;
}

87
disk-utils/raw.8 Normal file
View file

@ -0,0 +1,87 @@
.\" -*- nroff -*-
.TH RAW 8 "Aug 1999" "Version 0.1"
.SH NAME
raw \- bind a Linux raw character device
.SH SYNOPSIS
.B raw
.I /dev/raw<N> <major> <minor>
.PP
.B raw
.I /dev/raw<N> /dev/<blockdev>
.PP
.B raw
.B \-q
.I /dev/raw<N>
.PP
.B raw
.B \-qa
.SH DESCRIPTION
.B raw
is used to bind a Linux raw character device to a block device. Any
block device may be used: at the time of binding, the device driver does
not even have to be accessible (it may be loaded on demand as a kernel
module later).
.PP
.B raw
is used in two modes: it either sets raw device bindings, or it queries
existing bindings. When setting a raw device,
.I /dev/raw<N>
is the device name of an existing raw device node in the filesystem.
The block device to which it is to be bound can be specified either in
terms of its
.I major
and
.I minor
device numbers, or as a path name
.I /dev/<blockdev>
to an existing block device file.
.PP
The bindings already in existence can be queried with the
.I \-q
option, with is used either with a raw device filename to query that one
device, or with the
.I \-a
option to query all bound raw devices.
.PP
Once bound to a block device, a raw device can be opened, read and
written, just like the block device it is bound to. However, the raw
device does not behave exactly like the block device. In particular,
access to the raw device bypasses the kernel's block buffer cache
entirely: all I/O is done directly to and from the address space of the
process performing the I/O. If the underlying block device driver can
support DMA, then no data copying at all is required to complete the
I/O.
.PP
Because raw I/O involves direct hardware access to a process's memory, a
few extra restrictions must be observed. All I/Os must be correctly
aligned in memory and on disk: they must start at a sector offset on
disk, they must be an exact number of sectors long, and the data buffer
in virtual memory must also be aligned to a multiple of the sector
size. The sector size is 512 bytes for most devices.
.SH OPTIONS
.TP
.B -q
Set query mode.
.B raw
will query an existing binding instead of setting a new one.
.TP
.B -a
With
.B -q
, specifies that all bound raw devices should be queried.
.TP
.B -h
provides a usage summary.
.SH BUGS
The Linux
.B dd
(1) command does not currently align its buffers correctly, and so
cannot be used on raw devices.
.PP
Raw I/O devices do not maintain cache coherency with the Linux block
device buffer cache. If you use raw I/O to overwrite data already in
the buffer cache, the buffer cache will no longer correspond to the
contents of the actual storage device underneath. This is deliberate,
but is regarded either a bug or a feature depending on who you ask!
.SH AUTHOR
Stephen Tweedie (sct@redhat.com)

217
disk-utils/raw.c Normal file
View file

@ -0,0 +1,217 @@
/*
* raw.c: User mode tool to bind and query raw character devices.
*
* Stephen Tweedie, 1999
*
* This file may be redistributed under the terms of the GNU General
* Public License, version 2.
*
* Copyright Red Hat Software, 1999
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
#include <sys/raw.h>
char * progname;
int do_query = 0;
int do_query_all = 0;
int master_fd;
int raw_minor;
void open_raw_ctl(void);
int query(int minor, int quiet);
int bind (int minor, int block_major, int block_minor);
static void usage(int err)
{
fprintf(stderr,
"Usage:\n"
" %s /dev/rawN <major> <minor>\n"
" %s /dev/rawN /dev/<blockdev>\n"
" %s -q /dev/rawN\n"
" %s -qa\n",
progname, progname, progname, progname);
exit(err);
}
int main(int argc, char *argv[])
{
char c;
char * raw_name;
char * block_name;
int err;
int block_major, block_minor;
int i;
struct stat statbuf;
progname = argv[0];
while ((c = getopt(argc, argv, "ahq")) != EOF) {
switch (c) {
case 'a':
do_query_all = 1;
break;
case 'h':
usage(0);
case 'q':
do_query = 1;
break;
default:
usage(1);
}
}
/*
* Check for, and open, the master raw device, /dev/raw
*/
open_raw_ctl();
if (do_query_all) {
if (optind < argc)
usage(1);
for (i=1; i<255; i++)
query(i, 1);
exit(0);
}
/*
* It's a bind or a single query. Either way we need a raw device.
*/
if (optind >= argc)
usage(1);
raw_name = argv[optind++];
err = stat(raw_name, &statbuf);
if (err) {
fprintf (stderr, "Cannot locate raw device '%s' (%s)\n",
raw_name, strerror(errno));
exit(2);
}
if (!S_ISCHR(statbuf.st_mode)) {
fprintf (stderr, "raw device '%s' is not a character dev\n",
raw_name);
exit(2);
}
if (major(statbuf.st_rdev) != RAW_MAJOR) {
fprintf (stderr, "Device '%s' is not a raw dev\n",
raw_name);
exit(2);
}
raw_minor = minor(statbuf.st_rdev);
if (do_query)
return query(raw_minor, 0);
/*
* It's not a query, so we still have some parsing to do. Have
* we been given a block device filename or a major/minor pair?
*/
switch (argc - optind) {
case 1:
block_name = argv[optind];
err = stat(block_name, &statbuf);
if (err) {
fprintf (stderr,
"Cannot locate block device '%s' (%s)\n",
block_name, strerror(errno));
exit(2);
}
if (!S_ISBLK(statbuf.st_mode)) {
fprintf (stderr, "Device '%s' is not a block dev\n",
block_name);
exit(2);
}
block_major = major(statbuf.st_rdev);
block_minor = minor(statbuf.st_rdev);
break;
case 2:
block_major = strtol(argv[optind], 0, 0);
block_minor = strtol(argv[optind+1], 0, 0);
break;
default:
usage(1);
}
return bind(raw_minor, block_major, block_minor);
return 0;
}
void open_raw_ctl(void)
{
master_fd = open("/dev/raw", O_RDWR, 0);
if (master_fd < 0) {
fprintf (stderr,
"Cannot open master raw device '/dev/raw' (%s)\n",
strerror(errno));
exit(2);
}
}
int query(int minor, int quiet)
{
struct raw_config_request rq;
int err;
rq.raw_minor = minor;
err = ioctl(master_fd, RAW_GETBIND, &rq);
if (err < 0) {
if (quiet && errno == ENODEV)
return 3;
fprintf (stderr,
"Error querying raw device (%s)\n",
strerror(errno));
exit(3);
}
if (quiet && !rq.block_major && !rq.block_minor)
return 0;
printf ("/dev/raw%d: bound to major %d, minor %d\n",
minor, (int) rq.block_major, (int) rq.block_minor);
return 0;
}
int bind(int minor, int block_major, int block_minor)
{
struct raw_config_request rq;
int err;
rq.raw_minor = minor;
rq.block_major = block_major;
rq.block_minor = block_minor;
err = ioctl(master_fd, RAW_SETBIND, &rq);
if (err < 0) {
fprintf (stderr,
"Error setting raw device (%s)\n",
strerror(errno));
exit(3);
}
printf ("/dev/raw%d: bound to major %d, minor %d\n",
raw_minor, (int) rq.block_major, (int) rq.block_minor);
return 0;
}

View file

@ -113,14 +113,23 @@ main(int argc,char **argv)
{
int fd;
unsigned int cmd;
char *name;
char *progname, *p;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
name = argv[0];
if (argc < 3) usage(name);
if (argc == 2 &&
(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
printf(_("%s from %s\n"), progname, util_linux_version);
exit(0);
}
if (argc < 3) usage(progname);
cmd = FDSETPRM;
if (*argv[1] == '-') {
switch (argv[1][1]) {
@ -142,7 +151,7 @@ main(int argc,char **argv)
break;
#endif
default:
usage(name);
usage(progname);
}
argc--;
argv++;
@ -152,11 +161,11 @@ main(int argc,char **argv)
exit(1);
}
if (cmd != FDSETPRM && cmd != FDDEFPRM) {
if (argc != 2) usage(name);
if (argc != 2) usage(progname);
cmd_without_param(cmd,fd);
}
if (argc != 11 && argc != 3)
usage(name);
usage(progname);
else if (argc == 11)
set_params(cmd,fd,&argv[2]);
else

View file

@ -69,7 +69,6 @@
#endif
#include <signal.h>
#include <math.h>
#include <locale.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
@ -89,7 +88,6 @@ typedef long ext2_loff_t;
extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset,
unsigned int origin);
#include "../version.h"
#define VERSION UTIL_LINUX_VERSION
#define DEFAULT_DEVICE "/dev/hda"
@ -1316,7 +1314,7 @@ void new_part(int i)
int num_sects = last - first + 1;
int len, ext, j;
char *errmsg;
double sectors_per_MB = K*K / 512.0;
if (p_info[i].num == PRI_OR_LOG) {
static struct MenuItem menuPartType[]=
@ -1341,7 +1339,7 @@ void new_part(int i)
else
print_warning(_("!!! Internal error !!!"));
sprintf(def, "%.2f", ceiling(num_sects/(K*0.02))/100);
sprintf(def, "%.2f", num_sects/sectors_per_MB);
mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, _("Size (in MB): "));
if ((len = get_string(response, LINE_LENGTH, def)) <= 0 &&
len != GS_DEFAULT)
@ -2367,8 +2365,13 @@ void draw_partition(int i)
}
if (p_info[i].id > 0) {
char *dbn = my_basename(disk_device);
int l = strlen(dbn);
int digit_last = isdigit(dbn[l-1]);
mvprintw(y, NAME_START,
"%s%d", my_basename(disk_device), p_info[i].num+1);
"%s%s%d", dbn, (digit_last ? "p" : ""),
p_info[i].num+1);
if (p_info[i].flags) {
if (p_info[i].flags == ACTIVE_FLAG)
mvaddstr(y, FLAGS_START, _("Boot"));

View file

@ -6,3 +6,4 @@ struct systypes {
};
extern struct systypes i386_sys_types[];

View file

@ -7,7 +7,7 @@ fdisk \- Partition table manipulator for Linux
.SH SYNOPSIS
.BI "fdisk [\-u] " device
.sp
.BI "fdisk \-l [\-u] " "device ..."
.BI "fdisk \-l [\-u] [" "device ..." ]
.sp
.BI "fdisk \-s " "partition ..."
.sp
@ -175,11 +175,10 @@ Print version number of
program and exit.
.TP
.B \-l
List the partition tables for
.BR /dev/hd[a-d] ,
.BR /dev/sd[a-h] ,
.BR /dev/ed[a-d] ,
and then exit.
List the partition tables for the specified devices and then exit.
If no devices are given, those mentioned in
.I /proc/partitions
(if that exists) are used.
.TP
.B \-u
When listing partition tables, give sizes in sectors instead

View file

@ -94,7 +94,6 @@
#include <setjmp.h>
#include <errno.h>
#include <getopt.h>
#include <locale.h>
#include "nls.h"
#include <sys/stat.h>
@ -110,7 +109,6 @@
#include "fdisksgilabel.h"
#include "fdiskaixlabel.h"
#include "../version.h"
#include "../defines.h"
#ifdef HAVE_blkpg_h
#include <linux/blkpg.h>
@ -264,13 +262,6 @@ void fatal(enum failure why)
" 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");
break;
case no_partition:
message =_("Given name does not refer to a partition,\n"
"or maybe not even to a block device.\n");
break;
case unable_to_open:
sprintf(error, _("Unable to open %s\n"), disk_device);
break;
@ -805,7 +796,7 @@ read_hex(struct systypes *sys)
}
/*
* Print the message MESG, then read an integer between LOW and HIGH.
* Print the message MESG, then read an integer between LOW and HIGH (inclusive).
* If the user hits Enter, DFLT is returned.
* Answers like +10 are interpreted as offsets from BASE.
*
@ -1246,7 +1237,7 @@ void x_list_table(int extend)
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",
printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
i + 1, p->boot_ind, p->head,
sector(p->sector),
cylinder(p->sector, p->cyl), p->end_head,
@ -1370,7 +1361,7 @@ void verify(void)
void add_partition(int n, int sys)
{
char mesg[48];
char mesg[256]; /* 48 does not suffice in Japanese */
int i, read = 0;
struct partition *p = part_table[n], *q = part_table[ext_index];
uint start, stop = 0, limit, temp,
@ -1563,7 +1554,7 @@ void new_partition(void)
void write_table(void)
{
int i, error = 0;
int i;
changed[3] = changed[0] || changed[1] || changed[2] || changed[3];
if (!sun_label && !sgi_label) {
@ -1588,6 +1579,13 @@ void write_table(void)
}
printf(_("The partition table has been altered!\n\n"));
reread_partition_table(1);
}
void
reread_partition_table(int leave) {
int error = 0;
int i;
printf(_("Calling ioctl() to re-read partition table.\n"));
sync();
@ -1604,12 +1602,6 @@ void write_table(void)
error = errno;
}
close(fd);
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"),
@ -1621,7 +1613,14 @@ void write_table(void)
"partitions, please see the fdisk manual page for additional\n"
"information.\n"));
exit(0);
if (leave) {
close(fd);
printf(_("Syncing disks.\n"));
sync();
sleep(4); /* for sync() */
exit(!!i);
}
}
#define MAX_PER_LINE 16
@ -1693,7 +1692,7 @@ void xselect(void)
move_begin(get_partition(0, partitions));
break;
case 'c':
cylinders = read_int(1, cylinders, 65535,
cylinders = read_int(1, cylinders, 131071,
0, _("Number of cylinders"));
if (sun_label)
sun_set_ncyl(cylinders);
@ -1826,6 +1825,32 @@ void try(char *device, int user_specified)
}
}
/* for fdisk -l: try all things in /proc/partitions
that look like a partition name (do not end in a digit) */
void
tryprocpt() {
FILE *procpt;
char line[100], ptname[100], devname[120], *s;
int ma, mi, sz;
procpt = fopen(PROC_PARTITIONS, "r");
if (procpt == NULL) {
fprintf(stderr, _("cannot open %s\n"), PROC_PARTITIONS);
return;
}
while (fgets(line, sizeof(line), procpt)) {
if (sscanf (line, " %d %d %d %[^\n]\n",
&ma, &mi, &sz, ptname) != 4)
continue;
for(s = ptname; *s; s++);
if (isdigit(s[-1]))
continue;
sprintf(devname, "/dev/%s", ptname);
try(devname, 1);
}
}
int
dir_exists(char *dirname) {
struct stat statbuf;
@ -1837,8 +1862,7 @@ void
dummy(int *kk) {}
int
main(int argc, char **argv)
{
main(int argc, char **argv) {
int j, c;
int optl = 0, opts = 0;
int user_set_sector_size = 0;
@ -1892,7 +1916,6 @@ main(int argc, char **argv)
#endif
if (optl) {
listing = 1;
nowarn = 1;
type_open = O_RDONLY;
if (argc > optind) {
@ -1900,11 +1923,13 @@ main(int argc, char **argv)
/* avoid gcc warning:
variable `k' might be clobbered by `longjmp' */
dummy(&k);
listing = 1;
for(k=optind; k<argc; k++)
try(argv[k], 1);
} else {
/* we no longer have default device names */
fatal(usage2);
/* but, we can use /proc/partitions instead */
tryprocpt();
}
exit(0);
}

View file

@ -49,7 +49,7 @@ struct partition {
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};
unable_to_write, out_of_memory};
enum action {fdisk, require, try_only, create_empty};
@ -68,6 +68,7 @@ extern void list_types(struct systypes *sys);
extern int read_line (void);
extern char read_char(char *mesg);
extern int read_hex(struct systypes *sys);
extern void reread_partition_table(int leave);
uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
#define PLURAL 0
@ -83,3 +84,5 @@ extern int btrydev (char * dev);
/* prototypes for fdisksgilabel.c */
extern int valid_part_table_flag(unsigned char *b);
#define PROC_PARTITIONS "/proc/partitions"

View file

@ -75,7 +75,7 @@ static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int p
static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
static void sync_disks (void);
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
static int xbsd_translate_fstype (int linux_type);
static void xbsd_link_part (void);
#endif
@ -85,7 +85,7 @@ void alpha_bootblock_checksum (char *boot);
static struct xbsd_disklabel xbsd_dlabel;
static char buffer[BSD_BBSIZE];
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
static struct partition *xbsd_part;
static int xbsd_part_index;
#endif
@ -111,13 +111,13 @@ bmenu (void)
puts (_(" n add a new BSD partition"));
puts (_(" p print BSD partition table"));
puts (_(" q quit without saving changes"));
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
puts (_(" r return to main menu"));
#endif
puts (_(" s show complete disklabel"));
puts (_(" t change a partition's filesystem id"));
puts (_(" w write disklabel to disk"));
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
puts (_(" x link BSD partition to non-BSD partition"));
#endif
}
@ -134,7 +134,7 @@ is_netbsd_partition_type(int type) {
void
bselect (void) {
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
int t, ss;
for (t=0; t<4; t++)
@ -203,7 +203,7 @@ bselect (void) {
case 'w':
xbsd_write_disklabel ();
break;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
case 'r':
return;
case 'x':
@ -235,33 +235,35 @@ static void
xbsd_new_part (void)
{
uint begin, end;
char mesg[48];
char mesg[256];
int i;
if (!xbsd_check_new_partition (&i))
return;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
begin = get_start_sect(xbsd_part);
end = begin + get_nr_sects(xbsd_part) - 1;
#elif defined (__alpha__) || defined (__powerpc__)
begin = 0;
end = xbsd_dlabel.d_secperunit;
end = xbsd_dlabel.d_secperunit - 1;
#endif
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(SINGULAR));
if (display_in_cyl_units)
begin = (begin - 1) * units_per_sector;
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 (display_in_cyl_units)
{
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;
xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
@ -277,7 +279,7 @@ xbsd_print_disklabel (int show_all)
if (show_all)
{
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
fprintf(f, "# %s%d:\n", disk_device, xbsd_part_index+1);
#elif defined (__alpha__)
fprintf(f, "# %s:\n", disk_device);
@ -374,13 +376,14 @@ xbsd_print_disklabel (int show_all)
static void
xbsd_write_disklabel (void)
{
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
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);
xbsd_writelabel (NULL, &xbsd_dlabel);
#endif
reread_partition_table(0); /* no exit yet */
}
static int
@ -388,7 +391,7 @@ xbsd_create_disklabel (void)
{
char c;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
fprintf (stderr, _("%s%d contains no disklabel.\n"),
disk_device, xbsd_part_index+1);
#elif defined (__alpha__)
@ -398,7 +401,7 @@ xbsd_create_disklabel (void)
while (1)
if ((c = tolower (read_char (_("Do you want to create a disklabel? (y/n) ")))) == 'y')
{
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
if (xbsd_initlabel (xbsd_part, &xbsd_dlabel, xbsd_part_index) == 1)
#elif defined (__alpha__) || defined (__powerpc__)
if (xbsd_initlabel (NULL, &xbsd_dlabel, 0) == 1)
@ -529,7 +532,7 @@ xbsd_write_bootstrap (void)
bcopy (&dl, d, sizeof (struct xbsd_disklabel));
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
sector = get_start_sect(xbsd_part);
#elif defined (__powerpc__)
sector = 0;
@ -543,7 +546,7 @@ xbsd_write_bootstrap (void)
if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE))
fatal (unable_to_write);
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
printf (_("Bootstrap installed on %s%d.\n"), disk_device, xbsd_part_index+1);
#elif defined (__alpha__)
printf (_("Bootstrap installed on %s.\n"), disk_device);
@ -564,7 +567,7 @@ xbsd_change_fstype (void)
static int
xbsd_get_part_index (int max)
{
char prompt[40];
char prompt[256];
char l;
sprintf (prompt, _("Partition (a-%c): "), 'a' + max - 1);
@ -647,7 +650,7 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex)
d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
#endif
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
d -> d_flags = BSD_D_DOSPART;
#else
d -> d_flags = 0;
@ -670,7 +673,7 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex)
d -> d_bbsize = BSD_BBSIZE;
d -> d_sbsize = BSD_SBSIZE;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
d -> d_npartitions = 4;
pp = &d -> d_partitions[2]; /* Partition C should be the NetBSD partition */
pp -> p_offset = get_start_sect(p);
@ -696,7 +699,7 @@ xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
{
int t, sector;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
sector = (p ? get_start_sect(p) : 0);
#elif defined (__alpha__)
sector = 0;
@ -730,7 +733,7 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
{
int sector;
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
sector = get_start_sect(p) + BSD_LABELSECTOR;
#elif defined (__alpha__) || defined (__powerpc__)
sector = BSD_LABELSECTOR;
@ -771,7 +774,7 @@ sync_disks (void)
sleep (4);
}
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
static int
xbsd_translate_fstype (int linux_type)
{
@ -810,7 +813,7 @@ xbsd_link_part (void)
#if defined (__alpha__)
#if 0
#if !defined(__GLIBC__)
typedef unsigned long long u_int64_t;
#endif

View file

@ -43,7 +43,7 @@
#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
#if defined (i386) || defined (sparc)
#if defined (i386) || defined (__sparc__) || defined (__arm__)
#define BSD_LABELSECTOR 1
#define BSD_LABELOFFSET 0
#elif defined (__alpha__) || defined (__powerpc__)

View file

@ -671,7 +671,7 @@ sgi_delete_partition( int i )
void
sgi_add_partition( int n, int sys )
{
char mesg[48];
char mesg[256];
int first=0, last=0;
if( n == 10 ) {

View file

@ -472,7 +472,7 @@ void add_sun_partition(int n, int sys)
uint starts[8], lens[8];
int whole_disk = 0;
char mesg[48];
char mesg[256];
int i, first, last;
if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {

View file

@ -32,7 +32,7 @@
#define PROGNAME "sfdisk"
#define VERSION "3.07"
#define DATE "980518"
#define DATE "990908"
#include <stdio.h>
#include <stdlib.h> /* atoi, free */
@ -48,7 +48,6 @@
#include <linux/unistd.h> /* _syscall */
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/fs.h> /* BLKGETSIZE */
#include <locale.h>
#include "nls.h"
#include "common.h"
@ -829,7 +828,7 @@ void
out_partition_header(char *dev, int format, struct geometry G) {
if (dump) {
printf(_("# partition table of %s\n"), dev);
printf(_("unit: sectors\n\n"));
printf("unit: sectors\n\n");
return;
}
@ -929,12 +928,12 @@ out_partition(char *dev, int format, struct part_desc *p,
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;
@ -1012,16 +1011,24 @@ out_partition(char *dev, int format, struct part_desc *p,
void
out_partitions(char *dev, struct disk_desc *z) {
struct part_desc *p;
int pno, format = 0;
if (z->partno == 0)
printf(_("No partitions found\n"));
else {
if (get_fdisk_geometry(&(z->partitions[0])))
printf(_("Warning: The first partition looks like it was made\n"
for (pno=0; pno < z->partno; pno++) {
p = &(z->partitions[pno]);
if (p->size != 0 && p->p.sys_type != 0) {
if (get_fdisk_geometry(p))
printf(
_("Warning: The first partition looks like it was made\n"
" for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
"For this listing I'll assume that geometry.\n"),
F.heads, F.sectors, B.cylinders, B.heads, B.sectors);
break;
}
}
out_partition_header(dev, format, F);
for(pno=0; pno < z->partno; pno++) {
out_partition(dev, format, &(z->partitions[pno]), z, F);

View file

@ -20,6 +20,7 @@ all: $(USRGAMES)
# Rules for everything else
banner.o: $(LIB)/errs.h
banner: banner.o $(ERR_O)
ddate: ddate.o

View file

@ -39,7 +39,7 @@
* banner [-w#] [-d] [-t] message ...
*/
#include "err.h"
#include "errs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -47,6 +47,9 @@ 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.
.TP
.B \-V
Display a version number and exit.
.SH BUGS
Not all keyboards support all rates.
.PP

View file

@ -85,7 +85,6 @@ beats rebuilding the kernel!
#endif
#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,
@ -202,7 +201,7 @@ int main( int argc, char **argv )
textdomain(PACKAGE);
while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) {
while ( (c = getopt( argc, argv, "r:d:svVh?" )) != EOF ) {
switch (c) {
case 'r':
rate = atof( optarg );
@ -214,8 +213,14 @@ int main( int argc, char **argv )
silent = 1;
break;
case 'v':
case 'V':
fprintf( stderr, "util-linux %s kbdrate\n", UTIL_LINUX_VERSION);
exit(0);
case 'h':
case '?':
fprintf( stderr,
_("Usage: kbdrate [-V] [-s] [-r rate] [-d delay]\n"));
exit(0);
}
}

18
lib/README.widechar Normal file
View file

@ -0,0 +1,18 @@
From haible@ilog.fr Mon Sep 20 15:34:21 1999
Hello Andries,
Here is a patch for adding multi-byte locale support to a few programs
found in util-linux-2.9u. With these patches, the programs
col colcrt colrm column rev ul
now work correctly in UTF-8 locales. This is done by using the ISO C / SUSV2
i18n functions, therefore they will become effective when glibc-2.2 comes
out. For the moment, you can test the patches by
1. defining ENABLE_WIDECHAR in defines.h
2. Change the #if 0 to #if 1 in lib/widechar.h
3. Modify your CFLAGS and LDFLAGS to include the directories where libutf8
is installed.

112
lib/err.c
View file

@ -31,17 +31,13 @@
* SUCH DAMAGE.
*/
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <string.h>
#include "errs.h"
#include "../defines.h"
#ifdef HAVE_progname
@ -50,101 +46,63 @@ extern char *__progname; /* Program name, from crt0. */
char *__progname = "foo"; /* probably libc4 */
#endif
__dead void
#ifdef __STDC__
err(int eval, const char *fmt, ...)
#else
err(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
/* Some compilers complain "null format string" upon err(1,NULL) */
/* Make them happy with a separate routine. */
void
err_nomsg(int exitval) {
(void)fprintf(stderr, "%s: %s\n", __progname, strerror(errno));
exit(exitval);
}
void
err(int exitval, const char *fmt, ...) {
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verr(eval, fmt, ap);
verr(exitval, fmt, ap);
va_end(ap);
}
__dead void
verr(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
void
verr(int exitval, const char *fmt, va_list ap) {
int sverrno;
sverrno = errno;
(void)fprintf(stderr, "%s: ", __progname);
if (fmt != NULL) {
if (fmt != NULL && *fmt != 0) {
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, ": ");
}
(void)fprintf(stderr, "%s\n", strerror(sverrno));
exit(eval);
exit(exitval);
}
__dead void
#if __STDC__
errx(int eval, const char *fmt, ...)
#else
errx(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
void
errx(int exitval, const char *fmt, ...) {
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verrx(eval, fmt, ap);
verrx(exitval, fmt, ap);
va_end(ap);
}
__dead void
verrx(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
void
verrx(int exitval, const char *fmt, va_list ap) {
(void)fprintf(stderr, "%s: ", __progname);
if (fmt != NULL)
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, "\n");
exit(eval);
exit(exitval);
}
void
#if __STDC__
warn(const char *fmt, ...)
#else
warn(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
warn(const char *fmt, ...) {
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarn(fmt, ap);
va_end(ap);
}
void
vwarn(fmt, ap)
const char *fmt;
va_list ap;
{
vwarn(const char *fmt, va_list ap) {
int sverrno;
sverrno = errno;
@ -157,29 +115,15 @@ vwarn(fmt, ap)
}
void
#ifdef __STDC__
warnx(const char *fmt, ...)
#else
warnx(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
warnx(const char *fmt, ...) {
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(fmt, ap)
const char *fmt;
va_list ap;
{
vwarnx(const char *fmt, va_list ap) {
(void)fprintf(stderr, "%s: ", __progname);
if (fmt != NULL)
(void)vfprintf(stderr, fmt, ap);

View file

@ -1,70 +0,0 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)err.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _ERR_H_
#define _ERR_H_
#ifdef __linux__
#include <stdarg.h>
#define _BSD_VA_LIST_ va_list
#define __dead /* */
#else
/*
* Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two
* places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
* of them here we may collide with the utility's includes. It's unreasonable
* for utilities to have to include one of them to include err.h, so we get
* _BSD_VA_LIST_ from <machine/ansi.h> and use it.
*/
#include <machine/ansi.h>
#endif
#include <sys/cdefs.h>
__BEGIN_DECLS
__dead void err __P((int, const char *, ...));
__dead void verr __P((int, const char *, _BSD_VA_LIST_));
__dead void errx __P((int, const char *, ...));
__dead void verrx __P((int, const char *, _BSD_VA_LIST_));
void warn __P((const char *, ...));
void vwarn __P((const char *, _BSD_VA_LIST_));
void warnx __P((const char *, ...));
void vwarnx __P((const char *, _BSD_VA_LIST_));
__END_DECLS
#ifdef __linux__
#undef _BSD_VA_LIST_
#endif
#endif /* !_ERR_H_ */

16
lib/errs.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef _ERR_H_
#define _ERR_H_
#include <stdarg.h>
void err_nomsg (int);
void err (int, const char *, ...);
void verr (int, const char *, va_list);
void errx (int, const char *, ...);
void verrx (int, const char *, va_list);
void warn (const char *, ...);
void vwarn (const char *, va_list);
void warnx (const char *, ...);
void vwarnx (const char *, va_list);
#endif /* !_ERR_H_ */

View file

@ -1,43 +1,78 @@
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Vaguely based on
* @(#)pathnames.h 5.3 (Berkeley) 5/9/89
*
* Changed: Sun Nov 21 12:30:54 1993 by faith@cs.unc.edu
* Changed: Wed Jun 22 20:47:27 1994 by faith@cs.unc.edu, based on changes
* from poe@daimi.aau.dk
* Changed: Wed Jun 22 22:50:13 1994 by faith@cs.unc.edu
* Changed: Sat Feb 4 16:02:10 1995 by faith@cs.unc.edu
* Changed: Tue Jul 2 09:37:36 1996 by janl@math.uio.no, axp patches
* Changed: Thu Nov 9 21:58:36 1995 by joey@infodrom.north.de
* This code is in the public domain.
*/
#include <paths.h>
#ifndef __STDC__
# error "we need an ANSI compiler"
#endif
/* The paths for some of these are wrong in /usr/include/paths.h, but we
re-define them here. */
/* The paths for some of these are wrong in /usr/include/paths.h,
but we re-define them here. */
/* Used in login.c, agetty.c, simpleinit.c, shutdown.c, write.c */
#undef _PATH_UTMP
/* Used in login.c, agetty.c, simpleinit.c, shutdown.c, last.c */
#undef _PATH_WTMP
/* These four are used in login.c only */
#undef _PATH_DEFPATH
#undef _PATH_DEFPATH_ROOT
#undef _PATH_LASTLOG
#undef _PATH_MAILDIR
/*
* HISTORY
*
What is the history of these six, and related defines?
------------------------------------------------------------------------
_PATH_UTMP and UTMP_FILE and UTMP_FILENAME:
/etc/utmp > /var/adm/utmp > /var/run/utmp.
Traditionally we have /etc/utmp.
In <paths.h> we have /etc/utmp, but since 4.6.0 /var/adm/utmp
and since 5.0.9 (and in glibc2) /var/run/utmp.
In login/pathnames.h we have /etc/utmp, but since 4.6.6 /var/adm/utmp.
In <utmp.h> UTMP_FILE is defined as /etc/utmp, but in 4.6.* as _PATH_UTMP.
_PATH_WTMP and WTMP_FILE and WTMP_FILENAME:
/etc/wtmp > /usr/adm/wtmp > /var/adm/wtmp > /var/log/wtmp.
Traditionally we have /etc/wtmp.
In <paths.h> we have /usr/adm/wtmp, but since 4.5.13 /var/adm/wtmp,
and since 5.0.9 (and in glibc2) /var/log/wtmp.
In login/pathnames.h. we have /etc/wtmp, but since 4.6.6 /var/adm/wtmp.
In <utmp.h> WTMP_FILE is defined as /usr/adm/wtmp, but in 4.5.* as
/var/adm/wtmp, and in 4.6.* as _PATH_WTMP.
_PATH_DEFPATH)
Long ago this was ".:/bin:/usr/bin".
In <paths.h> libc 4.4.1-4.4.4 have "/usr/bin:/bin"
and libc 4.5.21-5.4.23 have "/usr/local/bin:/usr/bin:/bin:."
and libc 5.4.38-5.4.46 have "/usr/local/bin:/usr/bin:/bin".
In login/pathnames.h libc4 and libc5 have "/usr/local/bin:/bin:/usr/bin:."
_PATH_DEFPATH_ROOT)
Long ago this was identical to _PATH_DEFPATH.
In <paths.h> no definition is present before libc 4.5.13.
Libc 4.5.13 has "/bin:/usr/bin:/etc"
Libc 4.5.14-5.4.46 have "/sbin:/bin:/usr/sbin:/usr/bin"
In login/pathnames.h libc4 and libc5 have "/bin:/usr/bin:/etc"
_PATH_LASTLOG)
/etc/lastlog > /usr/adm/lastlog > /var/adm/lastlog > /var/log/lastlog.
Traditionally we have /etc/lastlog.
In <bsd/utmp.h> libc 4.4.1-4.5.12 have /usr/adm/lastlog, 4.5.13 and
later have /var/adm/lastlog.
In paths.h all libc5 and glibc2 versions have /var/log/lastlog.
In login/pathnames.h all libc4 and libc5 versions have /usr/adm/lastlog.
_PATH_MAILDIR)
/usr/spool/mail > /var/spool/mail > /var/mail.
Traditionally we have /usr/spool/mail.
In <paths.h> we have /usr/spool/mail, but since libc 4.5.13 /var/spool/mail.
In login/pathnames.h all libc4 versions have /var/spool/mail.
Libc5 and glibc 2.0-2.1 have /var/spool/mail, but glibc 2.1.1 has /var/mail.
------------------------------------------------------------------------*/
#ifndef SBINDIR
#define SBINDIR "/sbin"
@ -73,7 +108,10 @@
#define _PATH_DEFPATH_ROOT SBINDIR ":/bin:" USRSBINDIR ":/usr/bin"
#define _PATH_HUSHLOGIN ".hushlogin"
#define _PATH_LASTLOG LOGDIR "/lastlog"
#ifndef _PATH_MAILDIR
#define _PATH_MAILDIR VARPATH "/spool/mail"
#endif
#define _PATH_MOTDFILE "/etc/motd"
#define _PATH_NOLOGIN "/etc/nologin"
@ -87,18 +125,22 @@
#define _PATH_SECURE "/etc/securesingle"
#define _PATH_USERTTY "/etc/usertty"
/* used in login-utils/shutdown.c */
#define _PATH_MTAB "/etc/mtab"
#define _PATH_UMOUNT "/bin/umount"
#define UMOUNT_ARGS "umount", "-a"
#define SWAPOFF_ARGS "swapoff", "-a"
/* used in login-utils/setpwnam.h and login-utils/islocal.c */
#define _PATH_PASSWD "/etc/passwd"
/* used in login-utils/setpwnam.h */
#define _PATH_PTMP "/etc/ptmp"
#define _PATH_PTMPTMP "/etc/ptmptmp"
#define _PATH_GROUP "/etc/group"
#define _PATH_GTMP "/etc/gtmp"
#define _PATH_GTMPTMP "/etc/gtmptmp"
/* used in misc-utils/look.c */
#define _PATH_WORDS "/usr/dict/words"
#define _PATH_WORDS_ALT "/usr/dict/web2"

41
lib/widechar.h Normal file
View file

@ -0,0 +1,41 @@
/* Declarations for wide characters */
/* This file must be included last because the redefinition of wchar_t may
cause conflicts when system include files were included after it. */
#include "../defines.h" /* for ENABLE_WIDECHAR */
#ifdef ENABLE_WIDECHAR
# include <wchar.h>
# include <wctype.h>
#if 0 /* for testing on platforms without built-in wide character support */
# include <libutf8.h>
#endif
#else
# include <ctype.h>
/* Fallback for types */
# define wchar_t char
# define wint_t int
# define WEOF EOF
/* Fallback for input operations */
# define fgetwc fgetc
# define getwc getc
# define getwchar getchar
# define fgetws fgets
/* Fallback for output operations */
# define fputwc fputc
# define putwc putc
# define putwchar putchar
# define fputws fputs
/* Fallback for character classification */
# define iswgraph isgraph
# define iswprint isprint
# define iswspace isspace
/* Fallback for string functions */
# define wcschr strchr
# define wcsdup strdup
# define wcslen strlen
#endif

View file

@ -124,12 +124,12 @@ wall: wall.o ttymsg.o
ifeq "$(USE_TTY_GROUP)" "yes"
login.o: login.c $(LIB)/pathnames.h $(LIB)/setproctitle.c $(LIB)/setproctitle.h
$(CC) -c $(CFLAGS) $(PAMFL) -DUSE_TTY_GROUP login.c
mesg.o: mesg.c $(LIB)/err.h
mesg.o: mesg.c $(LIB)/errs.h
$(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c
else
login.o: $(LIB)/pathnames.h
$(CC) -c $(CFLAGS) $(PAMFL) login.c
mesg.o: $(LIB)/err.h
mesg.o: $(LIB)/errs.h
endif
passwd: passwd.o islocal.o setpwnam.o $(LIB)/env.o

View file

@ -8,6 +8,7 @@ agetty \- alternative Linux getty
.RI "[-l " login_program ]
.RI "[-I " init ]
.RI "[-t " timeout ]
.RI "[-H " login_host ]
.I port
.I baud_rate,...
.RI [ term ]
@ -17,6 +18,7 @@ agetty \- alternative Linux getty
.RI "[-l " login_program ]
.RI "[-I " init ]
.RI "[-t " timeout ]
.RI "[-H " login_host ]
.I baud_rate,...
.I port
.RI [ term ]
@ -120,6 +122,12 @@ This allows the use of a non-standard login program (for example,
one that asks for a dial-up password or that uses a different
password file).
.TP
\-H \fIlogin_host\fP
Write the specified \fIlogin_host\fP into the utmp file. (Normally,
no login host is given, since \fBagetty\fP is used for local hardwired
connections and consoles. However, this option can be useful for
identifying terminal concentrators and the like.
.TP
\-m
Try to extract the baud rate the CONNECT status message
produced by Hayes(tm)\-compatible modems. These status

View file

@ -237,6 +237,9 @@ void error P_((int va_alist));
char *progname;
/* Fake hostname for ut_host specified on command line. */
char *fakehost = NULL;
/* ... */
#ifdef DEBUGGING
#define debug(s) fprintf(dbf,s); fflush(dbf)
@ -390,7 +393,7 @@ parse_args(argc, argv, op)
extern int optind; /* getopt */
int c;
while (isascii(c = getopt(argc, argv, "I:Lf:hil:mt:wn"))) {
while (isascii(c = getopt(argc, argv, "I:LH:f:hil:mt:wn"))) {
switch (c) {
case 'I':
if (!(op->initstring = malloc(strlen(optarg)))) {
@ -435,6 +438,9 @@ parse_args(argc, argv, op)
case 'L': /* force local */
op->flags |= F_LOCAL;
break;
case 'H': /* fake login host */
fakehost = optarg;
break;
case 'f': /* custom issue file */
op->flags |= F_CUSTISSUE;
op->issue = optarg;
@ -547,6 +553,8 @@ update_utmp(line)
strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
strncpy(ut.ut_line, line, sizeof(ut.ut_line));
if (fakehost)
strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
time(&t);
ut.ut_time = t;
ut.ut_type = LOGIN_PROCESS;
@ -586,6 +594,8 @@ update_utmp(line)
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));
if (fakehost)
(void) strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
(void) lseek(ut_fd, -ut_size, 1);
(void) write(ut_fd, (char *) &ut, sizeof(ut));
(void) close(ut_fd);
@ -1160,7 +1170,7 @@ bcode(s)
void
usage()
{
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);
fprintf(stderr, _("Usage: %s [-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] line baud_rate,... [termtype]\n"), progname);
exit(1);
}

View file

@ -33,9 +33,7 @@
#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#include <locale.h>
#include "my_crypt.h"
#include "../version.h"
#include "nls.h"
#include "env.h"

View file

@ -37,7 +37,6 @@
#include <ctype.h>
#include <getopt.h>
#include "my_crypt.h"
#include "../version.h"
#include "nls.h"
#include "env.h"

View file

@ -35,14 +35,14 @@ these must be met, or the log in attempt will be denied and a
.B syslog
message will be generated. See the section on "Special Access Restrictions".
If the user is root, then the login must be occuring on a tty listed in
If the user is root, then the login must be occurring on a tty listed in
.IR /etc/securetty .
Failures will be logged with the
.B syslog
facility.
After these conditions are checked, the password will be requested and
checks (if a password is required for this username). Ten attempts
After these conditions have been checked, the password will be requested and
checked (if a password is required for this username). Ten attempts
are allowed before
.B login
dies, but after the first three, the response starts to get very slow.
@ -53,8 +53,8 @@ facility. This facility is also used to report any successful root logins.
If the file
.I .hushlogin
exists, then a "quiet" login is performed (this disables the checking
of the checking of mail and the printing of the last login time and
message of the day). Otherwise, if
of mail and the printing of the last login time and message of the day).
Otherwise, if
.I /var/log/lastlog
exists, the last login time is printed (and the current login is
recorded).

View file

@ -162,6 +162,23 @@
#include "setproctitle.h"
#endif
/*
* RedHat writes:
* we've got a REAL HACK to avoid telling people that they have
* mail because the imap server has left a turd in their inbox.
* It works, but it sucks...
* It turns out that the turd is always 523 bytes long, so we
* just check for that size.
*/
/*
* If you want to turn this strange hack off, set
#define REDHAT_IGNORED_MAILSIZE 0
* In case people complain, this may become a configuration option,
* or perhaps this hack is thrown out again.
* A better solution would be to check the contents of this file..
*/
#define REDHAT_IGNORED_MAILSIZE 523
#if 0
/* from before we had a lastlog.h file in linux */
struct lastlog
@ -241,12 +258,23 @@ const char *months[] =
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec" };
/* provided by Linus Torvalds 16-Feb-93 */
/* Nice and simple code provided by Linus Torvalds 16-Feb-93 */
/* Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
He writes: "Login performs open() on a tty in a blocking mode.
In some cases it may make login wait in open() for carrier infinitely,
for example if the line is a simplistic case of a three-wire serial
connection. I believe login should open the line in the non-blocking mode
leaving the decision to make a connection to getty (where it actually
belongs). */
void
opentty(const char * tty)
{
int i;
int fd = open(tty, O_RDWR);
int fd = open(tty, O_RDWR | O_NONBLOCK);
int flags = fcntl(fd, F_GETFL);
flags &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
for (i = 0 ; i < fd ; i++)
close(i);
@ -485,6 +513,12 @@ main(int argc, char **argv)
retcode = pam_set_item(pamh, PAM_TTY, tty);
PAM_FAIL_CHECK;
/* Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
so that the "login: " prompt gets localized. Unfortunately,
PAM doesn't have an interface to specify the "Password: " string (yet). */
retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
PAM_FAIL_CHECK;
#if 0
/* other than iso-8859-1
* one more time due to reset tty by PAM
@ -1050,7 +1084,8 @@ Michael Riepe <michael@stud.uni-hannover.de>
motd();
mail = getenv("MAIL");
if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
if (mail && stat(mail, &st) == 0 && st.st_size != 0
&& st.st_size != REDHAT_IGNORED_MAILSIZE) {
printf(_("You have %smail.\n"),
(st.st_mtime > st.st_atime) ? _("new ") : "");
}

View file

@ -48,12 +48,12 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "errs.h"
#include "nls.h"
int

View file

@ -68,8 +68,6 @@
#include "nls.h"
#include "env.h"
#include "../version.h"
#ifndef _PATH_CHFN
# define _PATH_CHFN "/usr/bin/chfn"
# define _PATH_CHSH "/usr/bin/chsh"

View file

@ -56,10 +56,7 @@
#include <unistd.h>
#include <utmp.h>
#include "nls.h"
#ifdef __linux__
#include <locale.h>
#include "pathnames.h"
#endif
void makemsg __P((char *));

View file

@ -10,8 +10,8 @@ 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 \
tsort.1 whereis.1 write.1
logger.1 look.1 mcookie.1 namei.1 rename.1 script.1 \
whereis.1 write.1
# Where to put binaries?
# See the "install" rule for the links. . .
@ -19,12 +19,7 @@ MAN1= cal.1 chkdupexe.1 ddate.1 kill.1 \
BIN= kill
USRBIN= cal chkdupexe ddate logger look mcookie \
namei script tsort whereis write
ifeq "$(HAVE_CLEAR)" "no"
USRBIN:=$(USRBIN) clear
MAN1:=$(MAN1) clear.1
endif
namei rename script whereis write
ifeq "$(HAVE_RESET)" "no"
USRBIN:=$(USRBIN) reset
@ -36,6 +31,11 @@ USRBIN:=$(USRBIN) setterm
MAN1:=$(MAN1) setterm.1
endif
ifeq "$(HAVE_TSORT)" "no"
USRBIN:=$(USRBIN) tsort
MAN1:=$(MAN1) tsort.1
endif
# For script only
LIBPTY=
ifeq "$(HAVE_OPENPTY)" "yes"
@ -69,9 +69,9 @@ $(NEEDS_OPENPTY):
# Rules for everything else
cal.o: $(LIB)/errs.h
cal: cal.o $(ERR_O)
chkdupexe: chkdupexe.pl
clear: clear.sh
kill: kill.o procs.o
logger: logger.o
mcookie: mcookie.o md5.o

View file

@ -52,9 +52,10 @@ the current month is displayed.
The options are as follows:
.Bl -tag -width Ds
.It Fl m
Display monday as the first day of the week.
Display Monday as the first day of the week.
(The default is Sunday.)
.It Fl j
Display julian dates (days one-based, numbered from January 1).
Display Julian dates (days one-based, numbered from January 1).
.It Fl y
Display a calendar for the current year.
.El

View file

@ -44,13 +44,13 @@
#include <sys/types.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <locale.h>
#include "errs.h"
#include "nls.h"
#include "../defines.h"
@ -138,6 +138,7 @@ void trim_trailing_spaces __P((char *));
void usage __P((void));
void yearly __P((int));
void headers_init(void);
extern char *__progname;
int
main(argc, argv)
@ -147,17 +148,17 @@ main(argc, argv)
struct tm *local_time;
time_t now;
int ch, month, year, yflag;
char *progname, *p;
#ifdef __linux__
extern char *__progname;
__progname = argv[0];
#endif
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
__progname = progname;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
setlocale(LC_ALL,"");
yflag = 0;
while ((ch = getopt(argc, argv, "mjy")) != EOF)
switch(ch) {
@ -170,6 +171,10 @@ main(argc, argv)
case 'y':
yflag = 1;
break;
case 'V':
printf(_("%s from %s\n"),
progname, util_linux_version);
return 0;
case '?':
default:
usage();
@ -254,7 +259,7 @@ monthly(month, year)
int month, year;
{
int col, row, len, days[MAXDAYS];
char *p, lineout[30];
char *p, lineout[300];
day_array(month, year, days);
len = sprintf(lineout, "%s %d", full_month[month - 1], year);
@ -481,6 +486,6 @@ void
usage()
{
(void)fprintf(stderr, _("usage: cal [-mjy] [[month] year]\n"));
(void)fprintf(stderr, _("usage: cal [-mjyV] [[month] year]\n"));
exit(1);
}

View file

@ -29,13 +29,18 @@ $execdirs='/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin '.
'/usr/TeX/bin /usr/tex/bin /usr/games '.
'/usr/local/games';
# Turn off buffering for the output channel.
$|=1;
# Values from /usr/include/linux/errno.h. Existence of linux/errno.ph is not
# something to count on... :-(
$ENOENT=2;
%didthis=();
foreach $dir (split(/\s+/, "$execdirs")) {
foreach $dir (split(/\s+/, "$execdirs"), "\0", split(/:/, $ENV{PATH})) {
if ($dir eq "\0") { $checkingpath = 1; next; }
# It's like this: One directory corresponds to one $device,$inode tuple
# If a symlink points to a directory we already checked that directory
@ -52,7 +57,7 @@ foreach $dir (split(/\s+/, "$execdirs")) {
print "Dangling symlink: $dir\n";
next;
}
# warn "Nonexistent directory: $dir\n";
warn "Nonexistent directory: $dir\n" if ($checkingpath);
next;
}
@ -90,7 +95,7 @@ foreach $dir (split(/\s+/, "$execdirs")) {
closedir(DIR);
}
open(LS,"| xargs ls -ldU");
open(LS,"| xargs -r ls -ldU");
while (($prog,$paths)=each %progs) {
print LS "$paths\n" if ($count{$prog}>1);
}

View file

@ -30,6 +30,7 @@
- added Native Language Support
*/
#include "../defines.h" /* for util-linux-version */
/* configuration options VVVVV READ THIS!!! */
@ -150,6 +151,11 @@ main (int argc, char *argv[])
struct disc_time hastur;
char schwa[23*17], *fnord=0;
int pi;
char *progname, *p;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@ -162,6 +168,8 @@ main (int argc, char *argv[])
case '+': fnord=argv[pi]+1; break;
case '-':
switch(argv[pi][1]) {
case 'V':
printf(_("%s from %s\n"), progname, util_linux_version);
default: goto usage;
}
default: goto thud;
@ -281,7 +289,7 @@ struct disc_time makeday(int imonth,int iday,int iyear) /*i for input */
funkychickens.day=dayspast+iday-1;
funkychickens.season=0;
if((funkychickens.year%4)==2) {
if (funkychickens.day==59) funkychickens.day=-1;
if (funkychickens.day==59 && iday==29) funkychickens.day=-1;
}
funkychickens.yday=funkychickens.day;
/* note: EQUAL SIGN...hopefully that fixes it */

73
misc-utils/ddate.doc Normal file
View file

@ -0,0 +1,73 @@
PERPETUAL DATE CONVERTER FROM GREGORIAN TO POEE CALENDAR
SEASONS
1. Chaos -- Patron Apostle Hung Mung
2. Discord -- Patron Apostle Dr. Van Van Mojo
3. Confusion -- Patron Apostle Sri Syadasti
4. Bureaucracy -- Patron Apostle Zarathud
5. The Aftermath -- Patron Apostle the Elder Malaclypse
DAYS OF THE WEEK*
1. Sweetmorn *The DAYS OF THE WEEK
2. Boomtime are named from the five
3. Pungenday basic elements: SWEET,
4. Prickle-Prickle BOOM, PUNGENT, PRICKLE,
5. Setting Orange and ORANGE.
HOLYDAYS
A. Apostle Holydays B. Seasons Holydays
1. Mungday 1. Chaoflux
2. Mojoday 2. Discoflux
3. Syaday 3. Confuflux
4. Zaraday 4. Bureflux
5. Maladay 5. Afflux
Each occurs on the 5th Each occurs on the 50th
day of the Season day of the Season
C. Saint Tib's Day -- occurs once every four years (1 + 4 = 5) and is
inserted between the 59th and 60th days of the Season of Chaos
ST BT PD PP SO SM BT PD PP SO
Jan 1 2 3 4 5 1 2 3 4 5 Chs Jul 5 6 7 8 9 40 41 42 43 44 Cfn
6 7 8 9 10 6 7 8 9 10 10 11 12 13 14 45 46 47 48 49
11 12 13 14 15 11 12 13 14 15 15 16 17 18 19 50 51 52 53 54
16 17 18 19 20 16 17 18 19 20 20 21 22 23 24 55 56 57 58 59
21 22 23 24 25 21 22 23 24 25 25 26 27 28 29 60 61 62 63 64
26 27 28 29 30 26 27 28 29 30 30 31 1 2 3 65 66 67 68 69
31 1 2 3 4 31 32 33 34 35 Aug 4 5 6 7 8 70 71 72 73 1 Bcy
Feb 5 6 7 8 9 36 37 38 39 40 9 10 11 12 13 2 3 4 5 6
10 11 12 13 14 41 42 43 44 45 14 15 16 17 18 7 8 9 10 11
15 16 17 18 19 46 47 48 49 50 19 20 21 22 23 12 13 14 15 16
20 21 22 23 24 51 52 53 54 55 24 25 26 27 28 17 18 19 20 21
25 26 27 28* 1 56 57 58 59 60 29 30 31 1 2 22 23 24 25 26
Mar 2 3 4 5 6 61 62 63 64 65 Sep 3 4 5 6 7 27 28 29 30 31
7 8 9 10 11 66 67 68 69 70 8 9 10 11 12 32 33 34 35 36
12 13 14 15 16 71 72 73 1 2 Dsc 13 14 15 16 17 37 38 39 40 41
17 18 19 20 21 3 4 5 6 7 18 19 20 21 22 42 43 44 45 46
22 23 24 25 26 8 9 10 11 12 23 24 25 26 27 47 48 49 50 51
27 28 29 30 31 13 14 15 16 17 28 29 30 1 2 52 53 54 55 56
Apr 1 2 3 4 5 18 19 20 21 22 Oct 3 4 5 6 7 57 58 59 60 61
6 7 8 9 10 23 24 25 26 27 8 9 10 11 12 62 63 64 65 66
11 12 13 14 15 28 29 30 31 32 13 14 15 16 17 67 68 69 70 71
16 17 18 19 20 33 34 35 36 37 18 19 20 21 22 72 73 1 2 3 Afm
21 22 23 24 25 38 39 40 41 42 23 24 25 26 27 4 5 6 7 8
26 27 28 29 30 43 44 45 46 47 28 29 30 31 1 9 10 11 12 13
May 1 2 3 4 5 48 49 50 51 52 Nov 2 3 4 5 6 14 15 16 17 18
6 7 8 9 10 53 54 55 56 57 7 8 9 10 11 19 20 21 22 23
11 12 13 14 15 58 59 60 61 62 12 13 14 15 16 24 25 26 27 28
16 17 18 19 20 63 64 65 66 67 17 18 19 20 21 29 30 31 32 33
21 22 23 24 25 68 69 70 71 72 22 23 24 25 26 34 35 36 37 38
26 27 28 29 30 73 1 2 3 4 Cfn 27 28 29 30 1 39 40 41 42 43
31 1 2 3 4 5 6 7 8 9 Dec 2 3 4 5 6 44 45 46 47 48
Jun 5 6 7 8 9 10 11 12 13 14 7 8 9 10 11 49 50 51 52 53
10 11 12 13 14 15 16 17 18 19 12 13 14 15 16 54 55 56 57 58
15 16 17 18 19 20 21 22 23 24 17 18 19 20 21 59 60 61 62 63
20 21 22 23 24 25 26 27 28 29 22 23 24 25 26 64 65 66 67 68
25 26 27 28 29 30 31 32 33 34 27 28 29 30 31 69 70 71 72 73
30 1 2 3 4 35 36 37 38 39 [1970 = 3136] [Next St. Tib's Day in 3138]
SACRED DOCUMENT OF THE FROGS (old Erisian poem):
73 Days hath
Chaos, Discord, Confusion, Bureaucracy, and Aftermath

View file

@ -38,6 +38,8 @@
* 1999-02-22 Arkadiusz Mikiewicz <misiek@misiek.eu.org>
* - added Native Language Support
*
* 1999-11-13 aeb Accept signal numers 128+s.
*
*/
#include <stdio.h>
@ -137,7 +139,7 @@ struct signv {
int main (int argc, char *argv[]);
extern char *mybasename(char *);
int signame_to_signum (char *sig);
int arg_to_signum (char *arg);
int arg_to_signum (char *arg, int mask);
void nosig (char *name);
void printsig (int sig);
void printsignals (FILE *fp);
@ -146,16 +148,19 @@ int kill_verbose (char *procname, int pid, int sig);
extern int *get_pids (char *, int);
char version_string[] = "kill v2.0\n";
char *whoami;
int main (int argc, char *argv[])
{
int errors, numsig, pid;
char *ep, *arg;
char *ep, *arg, *progname, *p;
int do_pid, do_kill, check_all;
int *pids, *ip;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@ -174,11 +179,16 @@ int main (int argc, char *argv[])
if (*arg != '-') {
break;
}
if (! strcmp (arg, "--")) {
argc--, argv++;
break;
}
if (! strcmp (arg, "-u")) {
return usage (0);
}
if (! strcmp (arg, "-v")) {
fputs (version_string, stdout);
if (! strcmp (arg, "-v") || ! strcmp (arg, "-V") ||
! strcmp (arg, "--version")) {
printf(_("%s from %s\n"), progname, util_linux_version);
return 0;
}
if (! strcmp (arg, "-a")) {
@ -193,9 +203,9 @@ int main (int argc, char *argv[])
if (argc > 2) {
return usage (1);
}
/* argc == 2 */
/* argc == 2, accept "kill -l $?" */
arg = argv[1];
if ((numsig = arg_to_signum (arg)) < 0) {
if ((numsig = arg_to_signum (arg, 1)) < 0) {
fprintf (stderr, _("%s: unknown signal %s\n"), whoami, arg);
return 1;
}
@ -217,7 +227,7 @@ int main (int argc, char *argv[])
return usage (1);
argc--, argv++;
arg = *argv;
if ((numsig = arg_to_signum (arg)) < 0) {
if ((numsig = arg_to_signum (arg, 0)) < 0) {
nosig (arg);
return 1;
}
@ -231,7 +241,7 @@ int main (int argc, char *argv[])
if (do_kill)
break;
arg++;
if ((numsig = arg_to_signum (arg)) < 0) {
if ((numsig = arg_to_signum (arg, 0)) < 0) {
return usage (1);
}
do_kill++;
@ -284,13 +294,15 @@ int signame_to_signum (char *sig)
return (-1);
}
int arg_to_signum (char *arg)
int arg_to_signum (char *arg, int maskbit)
{
int numsig;
char *ep;
if (isdigit (*arg)) {
numsig = strtol (arg, &ep, 10);
if (numsig >= NSIG && maskbit && (numsig & 128) != 0)
numsig -= 128;
if (*ep != 0 || numsig < 0 || numsig >= NSIG)
return (-1);
return (numsig);

View file

@ -31,6 +31,8 @@
.\"
.\" @(#)logger.1 8.1 (Berkeley) 6/6/93
.\"
.\" Section on valid facitily and level strings added by
.\" and1000@debian.org, 26 Oct 1997.
.Dd June 6, 1993
.Dt LOGGER 1
.Os BSD 4.3
@ -78,6 +80,11 @@ Mark every line in the log with the specified
Write to socket as specified with
.Ar socket
instead of builtin syslog routines.
.It --
End the argument list. This is to allow the
.Ar message
to start with a hyphen (\-). This feature was not present in the
original BSD logger command; it is a GNU-specific extra.
.It Ar message
Write the message to log; if not specified, and the
.Fl f
@ -88,6 +95,15 @@ provided, standard input is logged.
The
.Nm logger
utility exits 0 on success, and >0 if an error occurs.
.Pp
Valid facility names are: auth, authpriv (for security information of
a sensitive nature), cron, daemon, ftp, kern, lpr, mail, news,
security (deprecated synonym for auth), syslog, user, uucp, and local0
to local7, inclusive.
.Pp
Valid level names are: alert, crit, debug, emerg, err, error
(deprecated synonym for err), info, notice, panic (deprecated synonym
for emerg), warning, warn (deprecated synonym for warning).
.Sh EXAMPLES
.Bd -literal -offset indent -compact
logger System rebooted

View file

@ -210,6 +210,13 @@ main(argc, argv)
}
} else
while (fgets(buf, sizeof(buf), stdin) != NULL) {
/* glibc is buggy and adds an additional newline,
so we have to remove it here until glibc is fixed */
int len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (!usock)
syslog(pri, "%s", buf);
else

View file

@ -55,7 +55,11 @@ As
.Nm look
performs a binary search, the lines in
.Ar file
must be sorted.
must be sorted (where
.Xr sort 1
got the same options \-d and/or \-f that
.Nm look
is invoked with).
.Pp
If
.Ar file

View file

@ -74,7 +74,7 @@ char *string;
char *comparbuf;
static char *binary_search (char *, char *);
static int compare (char *, char *, int);
static int compare (char *, char *);
static void err (const char *fmt, ...);
static char *linear_search (char *, char *);
static int look (char *, char *);
@ -192,10 +192,6 @@ look(char *front, char *back)
* back points to the beginning of a line at or after the first
* matching line.
*
* Base of the Invariants.
* front = NULL;
* back = EOF;
*
* Advancing the Invariants:
*
* p = first newline after halfway point from front to back.
@ -232,7 +228,7 @@ binary_search(char *front, char *back)
* infinitely loop.
*/
while (p < back && back > front) {
if (compare(p, back, 1) == GREATER)
if (compare(p, back) == GREATER)
front = p;
else
back = p;
@ -257,7 +253,7 @@ char *
linear_search(char *front, char *back)
{
while (front < back) {
switch (compare(front, back, 1)) {
switch (compare(front, back)) {
case EQUAL: /* Found it. */
return (front);
break;
@ -280,8 +276,8 @@ print_from(char *front, char *back)
{
int eol;
while (front < back && compare(front, back, 1) == EQUAL) {
if (compare(front, back, fflag) == EQUAL) {
while (front < back && compare(front, back) == EQUAL) {
if (compare(front, back) == EQUAL) {
eol = 0;
while (front < back && !eol) {
if (putchar(*front) == EOF)
@ -311,7 +307,7 @@ print_from(char *front, char *back)
* in other locales.
*/
int
compare(char *s2, char *s2end, int nocase) {
compare(char *s2, char *s2end) {
int i;
char *p;
@ -326,7 +322,7 @@ compare(char *s2, char *s2end, int nocase) {
*p = 0;
/* and compare */
if (nocase)
if (fflag)
i = strncasecmp(comparbuf, string, stringlen);
else
i = strncmp(comparbuf, string, stringlen);

View file

@ -255,11 +255,12 @@ 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 ***\n"));
symcount = -1;
}
} else {
(void)printf("\n");
namei(sym, lev + 1);
}
break;
case S_IFCHR:

40
misc-utils/rename.1 Normal file
View file

@ -0,0 +1,40 @@
.\" Written by Andries E. Brouwer (aeb@cwi.nl)
.\" Placed in the public domain
.\"
.TH RENAME 1 "1 Januari 2000" "" "Linux Programmer's Manual"
.SH NAME
rename \- Rename files
.SH SYNOPSIS
.BI rename " from to file..."
.SH DESCRIPTION
.B rename
will rename the specified files by replacing the first occurrence of
.I from
in their name by
.IR to .
For example, given the files
.IR foo1 ", ..., " foo9 ", " foo10 ", ..., " foo278 ,
the commands
.RS
.nf
rename foo foo0 foo?
rename foo foo0 foo??
.fi
.RE
will turn them into
.IR foo001 ", ..., " foo009 ", " foo010 ", ..., " foo278 .
And
.RS
.nf
rename .htm .html *.htm
.fi
.RE
will fix the extension of your html files.
.SH "SEE ALSO"
.BR mv (1)

97
misc-utils/rename.c Normal file
View file

@ -0,0 +1,97 @@
/*
* rename.c - aeb 2000-01-01
*
--------------------------------------------------------------
#!/bin/sh
if [ $# -le 2 ]; then echo call: rename from to files; exit; fi
FROM="$1"
TO="$2"
shift
shift
for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
--------------------------------------------------------------
* This shell script will do renames of files, but may fail
* in cases involving special characters. Here a C version.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "nls.h"
static char *progname;
int
do_rename(char *from, char *to, char *s) {
char *newname, *where, *p, *q;
int flen, tlen, slen;
where = strstr(s, from);
if (where == NULL)
return 0;
flen = strlen(from);
tlen = strlen(to);
slen = strlen(s);
newname = malloc(tlen+slen+1);
if (newname == NULL) {
fprintf(stderr, _("%s: out of memory\n"), progname);
exit(1);
}
p = s;
q = newname;
while (p < where)
*q++ = *p++;
p = to;
while (*p)
*q++ = *p++;
p = where+flen;
while (*p)
*q++ = *p++;
*p = 0;
if (rename(s, newname) != 0) {
int errsv = errno;
fprintf(stderr, _("%s: renaming %s to %s failed: %s\n"),
progname, s, newname, strerror(errsv));
exit(1);
}
return 1;
}
int
main(int argc, char **argv) {
char *from, *to, *p;
int i, ct;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc == 2) {
if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
printf(_("%s from %s\n"),
progname, util_linux_version);
return 0;
}
}
if (argc < 3) {
fprintf(stderr, _("call: %s from to files...\n"), progname);
exit(1);
}
from = argv[1];
to = argv[2];
ct = 0;
for (i=3; i<argc; i++)
ct += do_rename(from, to, argv[i]);
return 0;
}

View file

@ -11,7 +11,6 @@ setterm \- set terminal attributes
.B "setterm [ \-reset ]"
.B "setterm [ \-initialize ]"
.B "setterm [ \-cursor [on|off] ]"
.B "setterm [ \-keyboard pc|olivetti|dutch|extended ]"
.B "setterm [ \-repeat [on|off] ]"
.B "setterm [ \-appcursorkeys [on|off] ]"
.B "setterm [ \-linewrap [on|off] ]"

View file

@ -12,7 +12,7 @@
*
* Sanity increases by Cafeine Addict [sic].
*
* Powersave features by, todd j. derr <tjd@wordsmith.org>
* Powersave features by todd j. derr <tjd@wordsmith.org>
*
* Converted to terminfo by Kars de Jong (jongk@cs.utwente.nl)
*
@ -27,7 +27,6 @@
* [ -reset ]
* [ -initialize ]
* [ -cursor [on|off] ]
* [ -keyboard pc|olivetti|dutch|extended ]
* [ -repeat [on|off] ]
* [ -appcursorkeys [on|off] ]
* [ -linewrap [on|off] ]
@ -162,7 +161,7 @@ extern int klogctl(int type, char *buf, int len);
/* Static variables. */
/* Option flags. Set if the option is to be invoked. */
int opt_term, opt_reset, opt_initialize, opt_cursor, opt_keyboard;
int opt_term, opt_reset, opt_initialize, opt_cursor;
int opt_linewrap, opt_snow, opt_softscroll, opt_default, opt_foreground;
int opt_background, opt_bold, opt_blink, opt_reverse, opt_underline;
int opt_store, opt_clear, opt_blank, opt_snap, opt_snapfile, opt_standout;
@ -252,33 +251,6 @@ int *bad_arg; /* Set to true if an error is detected. */
}
}
#if 0
void parse_keyboard(argc, argv, option, opt_keyboard, bad_arg)
int argc; /* Number of arguments for this option. */
char *argv[]; /* Arguments for this option. */
int *option; /* Keyboard flag to set. */
int *opt_keyboard; /* Keyboard type to set. */
int *bad_arg; /* Set to true if an error is detected. */
{
/* Parse a -keyboard specification. */
if (argc != 1 || *option) *bad_arg = TRUE;
*option = TRUE;
if (argc == 1) {
if (strcmp(argv[0], "pc") == 0)
*opt_keyboard = PC;
else if (strcmp(argv[0], "olivetti") == 0)
*opt_keyboard = OLIVETTI;
else if (strcmp(argv[0], "dutch") == 0)
*opt_keyboard = DUTCH;
else if (strcmp(argv[0], "extended") == 0)
*opt_keyboard = EXTENDED;
else
*bad_arg = TRUE;
}
}
#endif
void par_color(argc, argv, option, opt_color, bad_arg)
int argc; /* Number of arguments for this option. */
char *argv[]; /* Arguments for this option. */
@ -659,10 +631,6 @@ int *bad_arg; /* Set to true if an error is detected. */
parse_none(argc, argv, &opt_initialize, bad_arg);
else if (STRCMP(option, "cursor") == 0)
parse_switch(argc, argv, &opt_cursor, &opt_cu_on, bad_arg);
#if 0
else if (STRCMP(option, "keyboard") == 0)
parse_keyboard(argc, argv, &opt_keyboard, &opt_ke_type, bad_arg);
#endif
else if (STRCMP(option, "repeat") == 0)
parse_switch(argc, argv, &opt_repeat, &opt_rep_on, bad_arg);
else if (STRCMP(option, "appcursorkeys") == 0)
@ -752,7 +720,6 @@ char *prog_name; /* Name of this program. */
#if 0
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"));
@ -833,26 +800,6 @@ int vcterm; /* Set if terminal is a virtual console. */
putp(ti_entry("civis"));
}
#if 0
/* -keyboard pc|olivetti|dutch|extended. Vc only. */
if (opt_keyboard && vcterm) {
switch (opt_ke_type) {
case PC:
printf("%s%s%s", DCS, _("keyboard.pc"), ST);
break;
case OLIVETTI:
printf("%s%s%s", DCS, _("keyboard.olivetti"), ST);
break;
case DUTCH:
printf("%s%s%s", DCS, _("keyboard.dutch"), ST);
break;
case EXTENDED:
printf("%s%s%s", DCS, _("keyboard.extended"), ST);
break;
}
}
#endif
/* -linewrap [on|off]. Vc only (vt102) */
if (opt_linewrap && vcterm) {
if (opt_li_on)

View file

@ -0,0 +1,13 @@
#!/bin/sh
# This script reproduces the output of the Solaris hostid program.
# It might be put in /usr/bin/hostid or so.
# Note that the hostid program does not have any known uses
# and does not exist on other architectures.
# Copyright 1999 Peter Jones, <pjones@redhat.com> .
# GPL and all that good stuff apply.
(
idprom=`cat /proc/openprom/idprom`
echo $idprom|dd bs=1 skip=2 count=2
echo $idprom|dd bs=1 skip=27 count=6
echo
) 2>/dev/null

View file

@ -39,6 +39,7 @@
*/
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
@ -87,7 +88,7 @@ typedef struct _buf {
NODE *add_node(), *find_node();
void add_arc(), no_memory(), remove_node(), tsort();
char *grow_buf(), *malloc();
char *grow_buf();
int find_cycle(NODE *, NODE *, int, int);
extern int errno;
@ -168,8 +169,6 @@ grow_buf(bp, size)
char *bp;
int size;
{
char *realloc();
if (!(bp = realloc(bp, (u_int)size)))
no_memory();
return(bp);

View file

@ -1,7 +1,6 @@
include ../make_include
include ../MCONFIG
CC = gcc
CFLAGS = -I$(LIB) $(OPT)
WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes
DEFINES = -DHAVE_NFS
@ -9,17 +8,6 @@ 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
## 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)
@ -67,7 +55,7 @@ swapon: swapon.o version.o
losetup: losetup.o
$(LINK) $^ -o $@
mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h
mount.o umount.o nfsmount.o losetup.o fstab.o realpath.o sundries.o: sundries.h
mount.o umount.o fstab.o sundries.o: fstab.h
@ -89,6 +77,8 @@ umount.o: mount_constants.h
mount.o mount_by_label.o mount_guess_fstype.o: linux_fs.h
sundries.o realpath.o: realpath.h
nfsmount_clnt.o: nfsmount_clnt.c
$(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c

View file

@ -189,7 +189,11 @@ The documentation in
.BR mount (8)
is often more up-to-date.
.SH "SEE ALSO"
.BR getmntent "(3), " mount "(8), " swapon "(8), " nfs (5)
.BR getmntent (3),
.BR mount (8),
.BR swapon (8),
.BR fs (5)
.BR nfs (5)
.SH HISTORY
The
.B fstab

View file

@ -224,6 +224,23 @@ getmntoptfile (const char *file)
return NULL;
}
/* Find the entry (SPEC,FILE) in fstab */
struct mntentchn *
getfsspecfile (const char *spec, const char *file) {
struct mntentchn *mc;
for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
if (streq (mc->mnt_dir, file) && streq (mc->mnt_fsname, spec))
return mc;
for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
if ((streq (mc->mnt_dir, file) ||
streq (canonicalize(mc->mnt_dir), file))
&& (streq (mc->mnt_fsname, spec) ||
streq (canonicalize(mc->mnt_fsname), spec)))
break;
return mc;
}
/* Find the dir FILE in fstab. */
struct mntentchn *
getfsfile (const char *file) {
@ -401,6 +418,8 @@ lock_mtab (void) {
}
we_created_lockfile = 1;
} else {
static int tries = 0;
/* Someone else made the link. Wait. */
alarm(LOCK_TIMEOUT);
if (fcntl (fd, F_SETLKW, &flock) == -1) {
@ -410,7 +429,15 @@ lock_mtab (void) {
_("timed out") : strerror (errsv));
}
alarm(0);
/* Maybe limit the number of iterations? */
/* Limit the number of iterations - maybe there
still is some old /etc/mtab~ */
if (tries++ > 3) {
if (tries > 5)
die (EX_FILEIO, _("Cannot create link %s\n"
"Perhaps there is a stale lock file?\n"),
MOUNTED_LOCK);
sleep(1);
}
}
close(fd);

View file

@ -28,6 +28,7 @@ struct mntentchn *getmntfilesbackward (const char *file, struct mntentchn *mc);
struct mntentchn *fstab_head (void);
struct mntentchn *getfsfile (const char *file);
struct mntentchn *getfsspec (const char *spec);
struct mntentchn *getfsspecfile (const char *spec, const char *file);
struct mntentchn *getfsuuidspec (const char *uuid);
struct mntentchn *getfsvolspec (const char *label);

View file

@ -91,6 +91,7 @@ struct ntfs_super_block {
struct fat_super_block {
u_char s_dummy[3];
u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
/* mtools-3.9.4 writes "MTOOL394" */
u_char s_dummy2[32];
u_char s_label[11]; /* for DOS? */
u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */

View file

@ -103,7 +103,8 @@ int set_loop(const char *device, const char *file, int offset,
loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
if (encryption && (loopinfo.lo_encrypt_type = crypt_type(encryption))
< 0) {
fprintf(stderr,_("Unsupported encryption type %s\n"),encryption);
fprintf(stderr,_("Unsupported encryption type %s\n"),
encryption);
exit(1);
}
loopinfo.lo_offset = offset;
@ -129,7 +130,8 @@ int set_loop(const char *device, const char *file, int offset,
(islower(pass[i]) ? toupper(pass[i]) :
pass[i])-'A'+10 : pass[i]-'0') << (i & 7)*4;
else {
fprintf(stderr,_("Non-hex digit '%c'.\n"),pass[i]);
fprintf(stderr,_("Non-hex digit '%c'.\n"),
pass[i]);
exit(1);
}
break;
@ -183,6 +185,7 @@ int main(int argc, char **argv)
{
char *offset,*encryption;
int delete,off,c;
int res = 0;
int ro = 0;
setlocale(LC_ALL, "");
@ -219,9 +222,9 @@ int main(int argc, char **argv)
} else {
if (offset && sscanf(offset,"%d",&off) != 1)
usage();
set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
res = set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
}
return 0;
return res;
}
#else /* LOOP_SET_FD not defined */

View file

@ -14,8 +14,10 @@ rm -f loop.h
if [ -f /usr/include/linux/posix_types.h ]; then
echo '#include <linux/posix_types.h>' >> loop.h
echo '#undef dev_t' >> loop.h
echo '#define dev_t __kernel_dev_t' >> loop.h
else
echo '#undef dev_t' >> loop.h
echo '#define dev_t unsigned short' >> loop.h
fi

View file

@ -86,10 +86,10 @@ unmangle(char *s) {
/*
* fstat'ing the file and allocating a buffer holding all of it
* may be a bad idea: if the file is /proc/mounttab, the stat
* may be a bad idea: if the file is /proc/mounts, the stat
* returns 0.
* (On the other hand, mangling and unmangling is meaningless
* for /proc/mounttab.)
* for /proc/mounts.)
*/
mntFILE *

View file

@ -33,6 +33,8 @@
.\" 970914, reg: -s option
.\" 981111, K.Garloff: /etc/filesystems
.\" 990111, aeb: documented /sbin/mount.smbfs
.\" 990730, Yann Droneaud <lch@multimania.com>: updated page
.\" 991214, Elrond <Elrond@Wunder-Nett.org>: added some docs on devpts
.\"
.TH MOUNT 8 "14 September 1997" "Linux 2.0" "Linux Programmer's Manual"
.SH NAME
@ -175,6 +177,14 @@ instead of
in the
.I fstab
line.
The
.B owner
option is similar to the
.B user
option, with the restriction that the user must be the owner
of the special file. This may be useful e.g. for
.I /dev/fd
if a login script makes the console user owner of this device.
The programs
.B mount
@ -202,7 +212,11 @@ option below). It is possible to replace
by a symbolic link to
.IR /proc/mounts ,
but some information is lost that way, and in particular
working with the loop device will be less convenient.
working with the loop device will be less convenient. Also,
pathnames containing spaces are handled correctly by
.I /etc/mtab
but not (yet) by
.IR /proc/mounts .
.SH OPTIONS
The full set of options used by an invocation of
@ -294,31 +308,35 @@ The argument following the
is used to indicate the file system type. The file system types which are
currently supported are listed in
.IR linux/fs/filesystems.c :
.IR minix ,
.IR xiafs ,
.IR ext ,
.IR ext2 ,
.IR msdos ,
.IR umsdos ,
.IR vfat ,
.IR proc ,
.IR autofs ,
.IR devpts ,
.IR nfs ,
.IR iso9660 ,
.IR smbfs ,
.IR ncpfs ,
.IR adfs ,
.IR affs ,
.IR autofs ,
.IR coda ,
.IR coherent ,
.IR devpts ,
.IR efs ,
.IR ext ,
.IR ext2 ,
.IR hfs ,
.IR hpfs ,
.IR iso9660 ,
.IR minix ,
.IR msdos ,
.IR ncpfs ,
.IR nfs ,
.IR ntfs ,
.IR proc ,
.IR qnx4 ,
.IR romfs ,
.IR smbfs ,
.IR sysv ,
.IR udf ,
.IR ufs ,
.IR sysv ", " xenix ", " coherent .
Note that the last three are equivalent and that
.IR umsdos ,
.IR vfat ,
.IR xenix ,
.IR xiafs .
Note that coherent, sysv and xenix are equivalent and that
.I xenix
and
.I coherent
@ -355,6 +373,7 @@ option is given, or if the
.B auto
type is specified, the superblock is probed for the filesystem type
.RI ( minix ", " ext ", " ext2 ", " xiafs ", " iso9660 ", " romfs
.RI , ufs ", " ntfs ", " qnx4 ", " bfs
are supported).
If this probe fails, mount will try to read the file
.IR /etc/filesystems ,
@ -362,6 +381,7 @@ or, if that does not exist,
.IR /proc/filesystems .
All of the filesystem types listed there will be tried,
except for those that are labeled "nodev" (e.g.,
.IR devpts ,
.I proc
and
.IR nfs ).
@ -537,6 +557,32 @@ These options are accepted but ignored.
.SH "Mount options for coherent"
None.
.SH "Mount options for devpts"
The devpts file system is a pseudo file system, traditionally mounted on
.IR /dev/pts .
In order to acquire a pseudo terminal, a process opens
.IR /dev/ptmx ;
the number of the pseudo terminal is then made available to the process
and the pseudo terminal slave can be accessed as
.IR /dev/pts/ <number>.
.TP
\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
This sets the owner or the group of newly created PTYs to
the specified values. When nothing is specified, they will
be set to the UID and GID of the creating process.
For example, if there is a tty group with GID 5, then
.B gid=5
will cause newly created PTYs to belong to the tty group.
.TP
.BI mode= value
Set the mode of newly created PTYs to the specified value.
The default is 0600.
A value of
.B mode=620
and
.B gid=5
makes "mesg y" the default on newly created PTYs.
.SH "Mount options for ext"
None.
Note that the `ext' file system is obsolete. Don't use it.
@ -619,11 +665,15 @@ These options determine who can use the reserved blocks.
Instead of block 1, use block
.I n
as superblock. This could be useful when the filesystem has been damaged.
Usually, copies of the superblock are found every 8192 blocks: in
block 1, 8193, 16385, ...
(Thus, one gets hundreds or even thousands of copies of the superblock
on a big filesystem. I do not know of options to mke2fs that would
cause fewer copies to be written.)
(Earlier, copies of the superblock would be made every 8192 blocks: in
block 1, 8193, 16385, ... (and one got hundreds or even thousands
of copies on a big filesystem). Since version 1.08,
.B mke2fs
has a \-s (sparse superblock) option to reduce the number of backup
superblocks, and since version 1.15 this is the default. Note
that this may mean that ext2 filesystems created by a recent
.B mke2fs
cannot be mounted r/w under Linux 2.0.*.)
.TP
.BR grpquota " / " noquota " / " quota " / " usrquota
These options are accepted but ignored.
@ -638,7 +688,7 @@ and
.I vfat
filesystems.)
.TP
.BR blocksize=512 " / " blocksize=1024
.BR blocksize=512 " / " blocksize=1024 " / " blocksize=2048
Set blocksize (default 512).
.TP
\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
@ -673,6 +723,10 @@ that are sometimes used on Linux, but are not accepted by MS-DOS are
rejected. (+, =, spaces, etc.)
.RE
.TP
.BI codepage= value
Sets the codepage for converting to shortname characters on FAT
and VFAT filesystems. By default, codepage 437 is used.
.TP
.BR conv=b[inary] " / " conv=t[ext] " / " conv=a[uto]
The
.I fat
@ -703,6 +757,15 @@ For file systems mounted in binary mode, a conversion tool
(fromdos/todos) is available.
.RE
.TP
.BI cvf_format= module
Forces the driver to use the CVF (Compressed Volume File) module
.RI cvf_ module
instead of auto-detection. If the kernel supports kmod, the
cvf_format=xxx option also controls on-demand CVF module loading.
.TP
.BI cvf_option= option
Option passed to the CVF module.
.TP
.B debug
Turn on the
.I debug
@ -710,10 +773,15 @@ flag. A version string and a list of file system parameters will be
printed (these data are also printed if the parameters appear to be
inconsistent).
.TP
.BR fat=12 " / " fat=16
Specify either a 12 bit fat or a 16 bit fat. This overrides
.BR fat=12 " / " fat=16 " / " fat=32
Specify a 12, 16 or 32 bit fat. This overrides
the automatic FAT type detection routine. Use with caution!
.TP
.BI iocharset= value
Character set to use for converting between 8 bit characters
and 16 bit Unicode characters. The default is iso8859-1.
Long filenames are stored on disk in Unicode format.
.TP
.B quiet
Turn on the
.I quiet
@ -774,6 +842,9 @@ that it is read-only, of course).
.B norock
Disable the use of Rock Ridge extensions, even if available. Cf.\&
.BR map .
.B nojoliet
Disable the use of Microsoft Joliet extensions, even if available. Cf.\&
.BR map .
.TP
.BR check=r[elaxed] " / " check=s[trict]
With
@ -792,7 +863,7 @@ possibly overriding the information found in the Rock Ridge extensions.
(Default:
.BR uid=0,gid=0 .)
.TP
.BR map=n[ormal] " / " map=o[ff]
.BR map=n[ormal] " / " map=o[ff] " / " map=a[corn]
For non-Rock Ridge volumes, normal name translation maps upper
to lower case ASCII, drops a trailing `;1', and converts `;' to `.'.
With
@ -801,6 +872,10 @@ no name translation is done. See
.BR norock .
(Default:
.BR map=normal .)
.B map=acorn
is like
.BR map=normal
but also apply Acorn extensions if present.
.TP
.BI mode= value
For non-Rock Ridge volumes, give all files the indicated mode.
@ -821,7 +896,7 @@ Set the block size to the indicated value.
.BR conv=binary .)
Since Linux 1.3.54 this option has no effect anymore.
(And non-binary settings used to be very dangerous,
often leading to silent data corruption.)
possibly leading to silent data corruption.)
.TP
.B cruft
If the high byte of the file length contains other garbage,
@ -830,6 +905,12 @@ This implies that a file cannot be larger than 16MB.
The `cruft' option is set automatically if the entire CDROM
has a weird size (negative, or more than 800MB). It is also
set when volume sequence numbers other than 0 or 1 are seen.
.TP
.B session=x
Select number of session on multisession CD. (Since 2.3.4.)
.TP
.B sbsector=xxx
Session begins from sector xxx. (Since 2.3.4.)
.SH "Mount options for minix"
None.
@ -926,6 +1007,30 @@ Usually it just causes lots of trouble.
.B nolock
Do not use locking. Do not start lockd.
.SH "Mount options for ntfs"
.TP
.BI iocharset= name
Character set to use when returning file names.
Unlike VFAT, NTFS suppresses names that contain
unconvertible characters.
.TP
.BR utf8
Use UTF-8 for converting file names.
.TP
.B uni_xlate=[0|1|2]
For 0 (or `no' or `false') or 1 (or `yes' or `true'):
use the VFAT-style encoding for file names outside the current
character set. A value of 2 will disable the encoding with ":".
.TP
.B posix=[0|1]
If enabled (posix=1), the file system distinguishes between
upper and lower case. The 8.3 alias names are presented as
hard links instead of being suppressed.
.TP
\fBuid=\fP\fIvalue\fP, \fBgid=\fP\fIvalue\fP and \fBumask=\fP\fIvalue\fP
Set the file permission on the filesystem.
By default, the files are owned by root and not readable by somebody else.
.SH "Mount options for proc"
.TP
\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
@ -943,13 +1048,109 @@ to the mount system call. This argument is constructed by
.BR smbmount (8)
and the current version of
.B mount
(2.6c) does not know anything about smb.
(2.9w) does not know anything about smb.
.SH "Mount options for sysv"
None.
.SH "Mount options for udf"
.TP
.B gid=
Set the default group.
.TP
.B umask=
Set the default umask.
.TP
.B uid=
Set the default user.
.TP
.B unhide
Show otherwise hidden files.
.TP
.B undelete
Show deleted files in lists.
.TP
.B strict
Set strict conformance (unused).
.TP
.B utf8
(unused).
.TP
.B iocharset
(unused).
.TP
.B bs=
Set the block size. (May not work unless 2048.)
.TP
.B novrs
Skip volume sequence recognition.
.TP
.B session=
Set the CDROM session counting from 0. Default: last session.
.TP
.B anchor=
Override standard anchor location. Default: 256.
.TP
.B volume=
Override the VolumeDesc location. (unused)
.TP
.B partition=
Override the PartitionDesc location. (unused)
.TP
.B lastblock=
Set the last block of the filesystem.
.TP
.B fileset=
Override the fileset block location. (unused)
.TP
.B rootdir=
Override the root directory location. (unused)
.SH "Mount options for ufs"
None.
.TP
.BI ufstype= value
UFS is a file system widely used in different operating systems.
The problem are differences among implementations. Features of some
implementations are undocumented, so its hard to recognize the
type of ufs automatically.
That's why user must specify the type of ufs by mount option.
Possible values are:
.RS
.TP
.B old
Old format of ufs, this is the default, read only.
.TP
.B 44bsd
For filesystems created by a BSD-like system (NetBSD,FreeBSD,OpenBSD).
.TP
.B sun
For filesystems created by SunOS or Solaris on Sparc.
.TP
.B sunx86
For filesystems created by Solaris on x86.
.TP
.B nextstep
For filesystems created by NeXTStep (on NeXT station) (currently read only).
.TP
.B nextstep-cd
For NextStep CDROMs (block_size == 2048), read-only.
.TP
.B openstep
For filesystems created by OpenStep (currently read only).
.RE
.TP
.BI onerror= value
Set behaviour on error:
.RS
.TP
.B panic
If an error is encountered, cause a kernel panic.
.TP
.B [lock|umount|repair]
These mount options don't do anything at present;
when an error is encountered only a console message is printed.
.RE
.SH "Mount options for umsdos"
See mount options for msdos.
@ -984,6 +1185,11 @@ Allow two files with names that only differ in case.
First try to make a short name without sequence number,
before trying
.IR name~num.ext .
.TP
.B utf8
UTF8 is the filesystem safe 8-bit encoding of Unicode that is used
by the console. It can be be enabled for the filesystem with this option.
If `uni_xlate' gets set, UTF8 gets disabled.
.SH "Mount options for xenix"
None.

View file

@ -32,6 +32,8 @@
* - fixed strerr(errno) in gettext calls
* 1999-07-05 Hirokazu Takahashi <h-takaha@sss.abk.nec.co.jp>
* - fixed use of nouser option
* 1999-09-09 Michael K. Johnson <johnsonm@redhat.com>
* - added `owner' mount option
*/
#include <unistd.h>
@ -107,6 +109,7 @@ struct opt_map
#define MS_NOAUTO 0x80000000
#define MS_USERS 0x40000000
#define MS_USER 0x20000000
#define MS_OWNER 0x10000000
#define MS_LOOP 0x00010000
/* Options that we keep the mount system call from seeing. */
@ -115,9 +118,12 @@ struct opt_map
/* Options that we keep from appearing in the options field in the mtab. */
#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER)
/* OPTIONS that we make ordinary users have by default. */
/* Options that we make ordinary users have by default. */
#define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV)
/* Options that we make owner-mounted devices have by default */
#define MS_OWNERSECURE (MS_NOSUID|MS_NODEV)
const struct opt_map opt_map[] = {
{ "defaults", 0, 0, 0 }, /* default options */
{ "ro", 1, 0, MS_RDONLY }, /* read-only */
@ -137,6 +143,8 @@ const struct opt_map opt_map[] = {
{ "nousers", 0, 1, MS_USERS }, /* Forbid ordinary user to mount */
{ "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */
{ "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
{ "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
{ "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */
/* add new options here */
#ifdef MS_NOSUB
{ "sub", 0, 1, MS_NOSUB }, /* allow submounts */
@ -244,6 +252,8 @@ parse_opt (const char *opt, int *mask, char *extra_opts)
if ((om->mask == MS_USER || om->mask == MS_USERS)
&& !om->inv)
*mask |= MS_SECURE;
if ((om->mask == MS_OWNER) && !om->inv)
*mask |= MS_OWNERSECURE;
#ifdef MS_SILENT
if (om->mask == MS_SILENT && om->inv) {
mount_quiet = 1;
@ -377,6 +387,7 @@ create_mtab (void) {
/* count successful mount system calls */
static int mountcount = 0;
/* returns 0: OK, -1: error */
static int
mount5 (struct mountargs *args) {
int ret = mount (args->spec, args->node, args->type,
@ -386,9 +397,9 @@ mount5 (struct mountargs *args) {
return ret;
}
/* Mount a single file system. Return status,
so don't exit on non-fatal errors. */
/* Mount a single file system.
Return status: 0: OK, -1: error in errno, 1: other error
don't exit on non-fatal errors. */
static int
try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
@ -396,8 +407,14 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
if (*type && strcasecmp (*type, "auto") == 0)
*type = NULL;
if (!*type && !(flags & MS_REMOUNT))
if (!*type && !(flags & MS_REMOUNT)) {
*type = guess_fstype_from_superblock(spec);
if (*type && !strcmp(*type, "swap")) {
error(_("%s looks like swapspace - not mounted"), spec);
*type = NULL;
return 1;
}
}
if (*type || (flags & MS_REMOUNT)) {
args.type = *type;
@ -419,6 +436,7 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
const char *opts0, int freq, int pass, int bg, int ro) {
struct mntentchn mcn;
struct mntent mnt;
int mnt5_res = 0; /* only for gcc */
int mnt_err;
int flags;
char *extra_opts; /* written in mtab */
@ -438,6 +456,26 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
/* root may allow certain types of mounts by ordinary users */
if (suid) {
/* RedHat patch: allow owners to mount when fstab contains
the owner option. Note that this should never be used
in a high security environment, but may be useful to give
people at the console the possibility of mounting a floppy. */
if (flags & MS_OWNER) {
if (!strncmp(spec0, "/dev/", 5)) {
struct stat sb;
if (!stat(spec0, &sb)) {
if (getuid() == sb.st_uid)
flags |= MS_USER;
}
}
}
/* James Kehl <mkehl@gil.com.au> came with a similar patch:
allow an arbitrary user to mount when he is the owner of
the mount-point and has write-access to the device.
This is even less secure. Let me skip it for the time being;
there should be an explicit fstab line allowing such things. */
if (!(flags & (MS_USER | MS_USERS))) {
if (already (spec, node))
die (EX_USAGE, _("mount failed"));
@ -448,6 +486,9 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
user = getusername();
}
if (flags & MS_OWNER)
flags &= ~MS_OWNER;
/* quietly succeed for fstab entries that don't get mounted automatically */
if (all && (flags & MS_NOAUTO))
return 0;
@ -538,7 +579,8 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
sprintf(mountprog, "/sbin/mount.%s", type);
if (stat(mountprog, &statbuf) == 0) {
if (fork() == 0) {
int res;
if ((res = fork()) == 0) {
char *oo, *mountargs[10];
int i = 0;
@ -559,7 +601,7 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
mountargs[i] = NULL;
execv(mountprog, mountargs);
exit(1); /* exec failed */
} else if (fork() != -1) {
} else if (res != -1) {
int status;
wait(&status);
return status;
@ -572,10 +614,11 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
block_signals (SIG_BLOCK);
if (fake
|| (try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts)) == 0)
if (!fake)
mnt5_res = try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts);
if (fake || mnt5_res == 0) {
/* Mount succeeded, report this (if verbose) and write mtab entry. */
{
if (loop)
opt_loopdev = loopdev;
@ -630,11 +673,17 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
/* Mount failed, complain, but don't die. */
if (type == 0)
error (_("mount: you must specify the filesystem type"));
if (type == 0) {
if (suid)
error (_("mount: I could not determine the filesystem type, "
"and none was specified"));
else
switch (mnt_err)
{
error (_("mount: you must specify the filesystem type"));
} else if (mnt5_res != -1) {
/* should not happen */
error (_("mount: mount failed"));
} else {
switch (mnt_err) {
case EPERM:
if (geteuid() == 0) {
if (stat (node, &statbuf) || !S_ISDIR(statbuf.st_mode))
@ -775,6 +824,7 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
default:
error ("mount: %s", strerror (mnt_err)); break;
}
}
return EX_FAIL;
}

View file

@ -13,6 +13,9 @@
*
* Wed Nov 11 11:33:55 1998: K.Garloff@ping.de, try /etc/filesystems before
* /proc/filesystems
* [This was mainly in order to specify vfat before fat; these days we often
* detect *fat and then assume vfat, so perhaps /etc/filesystems isnt
* so useful anymore.]
*
* 1999-02-22 Arkadiusz Mikiewicz <misiek@misiek.eu.org>
* - added Native Language Support
@ -67,12 +70,17 @@ swapped(unsigned short a) {
Added ufs from a patch by jj. But maybe there are several types of ufs?
Added ntfs from a patch by Richard Russon.
Added a very weak heuristic for vfat - aeb
Added qnx4 - aeb
Added swap - aeb
Currently supports: minix, ext, ext2, xiafs, iso9660, romfs, ufs, ntfs, vfat
Currently supports: minix, ext, ext2, xiafs, iso9660, romfs,
ufs, ntfs, vfat, qnx4, bfs
*/
static char
*magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs",
"ufs", "ntfs" };
"ufs", "ntfs", "qnx4", "bfs", "udf",
"swap" /* last - just to warn the user */
};
static int
tested(const char *device) {
@ -84,6 +92,32 @@ tested(const char *device) {
return 0;
}
/* udf magic - I find that trying to mount garbage as an udf fs
causes a very large kernel delay, almost killing the machine.
So, we do not try udf unless there is positive evidence that it
might work. Try iso9660 first, it is much more likely.
Strings below taken from ECMA 167. */
static char
*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
"NSR03", "TEA01" };
static int
may_be_udf(const char *id) {
char **m;
for (m = udf_magic; m - udf_magic < SIZE(udf_magic); m++)
if (!strncmp(*m, id, 5))
return 1;
return 0;
}
static int
may_be_swap(const char *s) {
return (strncmp(s-10, "SWAP-SPACE", 10) == 0 ||
strncmp(s-10, "SWAPSPACE2", 10) == 0);
}
static char *
fstype(const char *device) {
int fd;
@ -96,6 +130,8 @@ fstype(const char *device) {
union {
struct xiafs_super_block xiasb;
char romfs_magic[8];
char qnx4fs_magic[10]; /* ignore first 4 bytes */
long bfs_magic;
struct ntfs_super_block ntfssb;
struct fat_super_block fatsb;
} xsb;
@ -141,11 +177,17 @@ fstype(const char *device) {
type = "xiafs";
else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8))
type = "romfs";
else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
type = "qnx4fs";
else if(xsb.bfs_magic == 0x1badface)
type = "bfs";
else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC,
sizeof(xsb.ntfssb.s_magic)))
type = "ntfs";
else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) ||
!strncmp(xsb.fatsb.s_os, "MSWIN", 5))
!strncmp(xsb.fatsb.s_os, "MSWIN", 5) ||
!strncmp(xsb.fatsb.s_os, "MTOOL", 5) ||
!strncmp(xsb.fatsb.s_os, "mkdosfs", 7))
&& (!strncmp(xsb.fatsb.s_fs, "FAT12 ", 8) ||
!strncmp(xsb.fatsb.s_fs, "FAT16 ", 8) ||
!strncmp(xsb.fatsb.s_fs2, "FAT32 ", 8)))
@ -169,6 +211,28 @@ fstype(const char *device) {
if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0
|| strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0)
type = "iso9660";
else if (may_be_udf(isosb.iso.id))
type = "udf";
}
if (!type) {
/* perhaps the user tries to mount the swap space
on a new disk; warn her before she does mke2fs on it */
int pagesize = getpagesize();
int rd;
char buf[32768];
rd = pagesize;
if (rd < 8192)
rd = 8192;
if (rd > sizeof(buf))
rd = sizeof(buf);
if (lseek(fd, 0, SEEK_SET) != 0
|| read(fd, buf, rd) != rd)
goto io_error;
if (may_be_swap(buf+pagesize) ||
may_be_swap(buf+4096) || may_be_swap(buf+8192))
type = "swap";
}
close (fd);
@ -186,11 +250,13 @@ guess_fstype_from_superblock(const char *spec) {
if (verbose) {
printf (_("mount: you didn't specify a filesystem type for %s\n"),
spec);
if (type)
printf (_(" I will try type %s\n"), type);
else
if (!type)
printf (_(" I will try all types mentioned in %s or %s\n"),
ETC_FILESYSTEMS, PROC_FILESYSTEMS);
else if (!strcmp(type, "swap"))
printf (_(" and it looks like this is swapspace\n"));
else
printf (_(" I will try type %s\n"), type);
}
return type;
}
@ -237,17 +303,24 @@ is_in_procfs(const char *type) {
return 0;
}
/* return: 0: OK, -1: error in errno, 1: type not found */
/* when 1 is returned, *type is NULL */
int
procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **type) {
char *fsname;
*type = NULL;
if (!procfsopen())
return -1;
return 1;
while ((fsname = procfsnext()) != NULL) {
if (tested (fsname))
continue;
args->type = fsname;
if (verbose) {
printf(_("Trying %s\n"), fsname);
fflush(stdout);
}
if ((*mount_fn) (args) == 0) {
*type = xstrdup(fsname);
procfsclose();
@ -255,13 +328,11 @@ procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
} else if (errno != EINVAL) {
*type = "guess";
procfsclose();
return 1;
return -1;
}
}
procfsclose();
*type = NULL;
return -1;
return 1;
}
int

View file

@ -13,170 +13,109 @@
* GNU Library Public License for more details.
*/
#define HAVE_GETCWD
/*
* This routine is part of libc. We include it nevertheless,
* since the libc version has some security flaws.
*/
#ifdef __linux__
extern char *realpath(const char *path, char *resolved_path);
#define HAVE_UNISTD_H
#define HAVE_STRING_H
#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#if defined(HAVE_UNISTD_H) || defined(STDC_HEADERS)
#include <unistd.h>
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef _POSIX_VERSION
#include <limits.h> /* for PATH_MAX */
#else
#include <sys/param.h> /* for MAXPATHLEN */
#endif
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h> /* for S_IFLNK */
#ifndef PATH_MAX
#ifdef _POSIX_VERSION
#define PATH_MAX _POSIX_PATH_MAX
#else
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#include "realpath.h"
#include "sundries.h" /* for xstrdup */
#define MAX_READLINKS 32
#ifdef __STDC__
char *realpath(const char *path, char *resolved_path)
#else
char *realpath(path, resolved_path)
const char *path;
char *resolved_path;
#endif
{
char copy_path[PATH_MAX];
char link_path[PATH_MAX];
char *new_path = resolved_path;
char *max_path;
char *
myrealpath(const char *path, char *resolved_path, int maxreslth) {
char *npath;
char link_path[PATH_MAX+1];
int readlinks = 0;
int n;
/* Make a copy of the source path since we may need to modify it. */
if (strlen(path) >= PATH_MAX) {
errno = ENAMETOOLONG;
return NULL;
}
strcpy(copy_path, path);
path = copy_path;
max_path = copy_path + PATH_MAX - 2;
npath = resolved_path;
/* If it's a relative pathname use getwd for starters. */
/* If it's a relative pathname use getcwd for starters. */
if (*path != '/') {
#ifdef HAVE_GETCWD
getcwd(new_path, PATH_MAX - 1);
#else
getwd(new_path);
#endif
new_path += strlen(new_path);
if (new_path[-1] != '/')
*new_path++ = '/';
}
else {
*new_path++ = '/';
getcwd(npath, maxreslth-2);
npath += strlen(npath);
if (npath[-1] != '/')
*npath++ = '/';
} else {
*npath++ = '/';
path++;
}
/* Expand each slash-separated pathname component. */
while (*path != '\0') {
/* Ignore stray "/". */
/* Ignore stray "/" */
if (*path == '/') {
path++;
continue;
}
if (*path == '.') {
/* Ignore ".". */
if (path[1] == '\0' || path[1] == '/') {
if (*path == '.' && (path[1] == '\0' || path[1] == '/')) {
/* Ignore "." */
path++;
continue;
}
if (path[1] == '.') {
if (path[2] == '\0' || path[2] == '/') {
if (*path == '.' && path[1] == '.' &&
(path[2] == '\0' || path[2] == '/')) {
/* Backup for ".." */
path += 2;
/* Ignore ".." at root. */
if (new_path == resolved_path + 1)
continue;
/* Handle ".." by backing up. */
while ((--new_path)[-1] != '/')
while (npath > resolved_path+1 &&
(--npath)[-1] != '/')
;
continue;
}
}
}
/* Safely copy the next pathname component. */
while (*path != '\0' && *path != '/') {
if (path > max_path) {
if (npath-resolved_path > maxreslth-2) {
errno = ENAMETOOLONG;
return NULL;
}
*new_path++ = *path++;
*npath++ = *path++;
}
#ifdef S_IFLNK
/* Protect against infinite loops. */
if (readlinks++ > MAX_READLINKS) {
errno = ELOOP;
return NULL;
}
/* See if latest pathname component is a symlink. */
*new_path = '\0';
n = readlink(resolved_path, link_path, PATH_MAX - 1);
*npath = '\0';
n = readlink(resolved_path, link_path, PATH_MAX);
if (n < 0) {
/* EINVAL means the file exists but isn't a symlink. */
if (errno != EINVAL)
return NULL;
}
else {
} else {
/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
if (*link_path == '/')
/* Start over for an absolute symlink. */
new_path = resolved_path;
npath = resolved_path;
else
/* Otherwise back up over this component. */
while (*(--new_path) != '/')
while (*(--npath) != '/')
;
/* Safe sex check. */
if (strlen(path) + n >= PATH_MAX) {
if (strlen(path) + n >= sizeof(link_path)) {
errno = ENAMETOOLONG;
return NULL;
}
/* Insert symlink contents into path. */
strcat(link_path, path);
strcpy(copy_path, link_path);
path = copy_path;
path = xstrdup(link_path);
}
#endif /* S_IFLNK */
*new_path++ = '/';
*npath++ = '/';
}
/* Delete trailing slash but don't whomp a lone slash. */
if (new_path != resolved_path + 1 && new_path[-1] == '/')
new_path--;
if (npath != resolved_path+1 && npath[-1] == '/')
npath--;
/* Make sure it's null terminated. */
*new_path = '\0';
*npath = '\0';
return resolved_path;
}

1
mount/realpath.h Normal file
View file

@ -0,0 +1 @@
extern char *myrealpath(const char *path, char *resolved_path, int m);

View file

@ -14,6 +14,7 @@
#include <mntent.h> /* for MNTTYPE_SWAP */
#include "fstab.h"
#include "sundries.h"
#include "realpath.h"
#include "nfsmount.h"
#include "nls.h"
@ -224,9 +225,9 @@ canonicalize (const char *path) {
if (streq(path, "none") || streq(path, "proc") || streq(path, "devpts"))
return xstrdup(path);
canonical = xmalloc (PATH_MAX + 1);
canonical = xmalloc (PATH_MAX+2);
if (realpath (path, canonical))
if (myrealpath (path, canonical, PATH_MAX+1))
return canonical;
free(canonical);

Some files were not shown because too many files have changed in this diff Show more