summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaMont Jones <lamont@debian.org>2010-09-06 14:13:57 -0600
committerLaMont Jones <lamont@debian.org>2010-09-06 14:13:57 -0600
commiteb3eeb38b6129c7236e9661e12f49bf8e42c085f (patch)
tree9db4616b5c80323fd9b660edc1e48972adc7aca9
parent0864d694ca05ea9383ef09bc1bc3a182e15e2ffa (diff)
parent73356e0553bd9ac00f556891a4798064c0ee6849 (diff)
downloadutil-linux-old-eb3eeb38b6129c7236e9661e12f49bf8e42c085f.tar.gz
Merge remote branch 'origin/master'
Conflicts: mount/lomount.c
-rw-r--r--DEPRECATED12
-rw-r--r--Makefile.am2
-rw-r--r--README.devel2
-rw-r--r--TODO4
-rw-r--r--disk-utils/blockdev.8120
-rw-r--r--disk-utils/blockdev.c16
-rw-r--r--fdisk/cfdisk.c19
-rw-r--r--fdisk/fdisk.c50
-rw-r--r--fsck/Makefile.am2
-rw-r--r--fsck/base_device.c169
-rw-r--r--fsck/fsck.813
-rw-r--r--fsck/fsck.c89
-rw-r--r--fsck/fsck.h5
-rw-r--r--include/blkdev.h77
-rw-r--r--lib/blkdev.c2
-rw-r--r--login-utils/agetty.820
-rw-r--r--login-utils/agetty.c29
-rw-r--r--misc-utils/findmnt.c3
-rw-r--r--mount/fstab.5105
-rw-r--r--mount/fstab.c18
-rw-r--r--mount/fstab.h1
-rw-r--r--mount/lomount.c47
-rw-r--r--mount/mount.816
-rw-r--r--mount/mount.c30
-rw-r--r--mount/sundries.c4
-rw-r--r--mount/umount.84
-rw-r--r--mount/umount.c17
-rw-r--r--shlibs/blkid/src/partitions/partitions.c2
-rw-r--r--shlibs/blkid/src/superblocks/ext.c47
-rw-r--r--shlibs/mount/src/mountP.h2
-rw-r--r--shlibs/mount/src/utils.c27
-rw-r--r--sys-utils/dmesg.c5
-rw-r--r--sys-utils/flock.c2
-rw-r--r--sys-utils/lscpu.14
-rw-r--r--sys-utils/lscpu.c145
-rw-r--r--tests/expected/blkid/md-raid0-whole51
-rw-r--r--tests/expected/fdisk/id5
-rw-r--r--tests/expected/lscpu/lscpu-i386-amdshanghai1
-rw-r--r--tests/expected/lscpu/lscpu-i386-dellpe7001
-rw-r--r--tests/expected/lscpu/lscpu-i386-intels5000phb1
-rw-r--r--tests/expected/lscpu/lscpu-x86_64-dellr7101
-rw-r--r--tests/expected/lscpu/lscpu-x86_64-hpdl5851
-rw-r--r--tests/expected/lscpu/lscpu-x86_64-ibme326m1
-rw-r--r--tests/expected/lscpu/lscpu-x86_64-necem141
-rwxr-xr-xtests/ts/blkid/md-raid0-whole86
-rwxr-xr-xtests/ts/fdisk/id37
-rwxr-xr-xtests/ts/lscpu/lscpu3
-rw-r--r--text-utils/rev.c195
-rw-r--r--text-utils/tailf.c11
49 files changed, 883 insertions, 622 deletions
diff --git a/DEPRECATED b/DEPRECATED
index f5202434..457fb229 100644
--- a/DEPRECATED
+++ b/DEPRECATED
@@ -2,27 +2,31 @@ The following is a list of commands or features that are deprecated. All
deprecated utils are in maintenace mode and we keep them in source tree for
backward compatibilty only.
+What: line(1) command
+Since: 2.19
+Why: useless, nobody uses this command, head(1) is better
+
+--------------------------
+
What: losetup -s
-When: 2.15
+Since: 2.15
Why: the option -s is in collision with the Loop-AES losetup dialect that is used
in some distributions. Use the long version (--show) only.
--------------------------
What: cryptoloop support in mount/losetup
-When: undefined yet
Why: depreciated in favor of dm-crypt.
---------------------------
What: elvtune
-When: undefined yet
Why: useless for kernel >= 2.6.9
---------------------------
What: arch(1) command
-When: 2.14
+Since: 2.14
Why: deprecated in favor of uname(1) or arch(1) from coreutils
The arch(1) has been added (during 2.13 development cycle) to coreutuls
diff --git a/Makefile.am b/Makefile.am
index c489665f..9febbfd9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,8 +44,10 @@ SUBDIRS += mount
endif
if BUILD_FSCK
+if BUILD_LIBBLKID
SUBDIRS += fsck
endif
+endif
ACLOCAL_AMFLAGS = -I m4
diff --git a/README.devel b/README.devel
index 3ffc9c08..fdfa2644 100644
--- a/README.devel
+++ b/README.devel
@@ -17,7 +17,7 @@ AUTOTOOLS:
PATCHES:
* send your patches to the mailing list or to the upstream maintainer
- (see the AUTHORS file)
+ (see the AUTHORS and README files)
* diff -u
diff --git a/TODO b/TODO
index 020e6ea0..62c2cbb5 100644
--- a/TODO
+++ b/TODO
@@ -21,6 +21,7 @@ libblkid
...
blkid_unref(tp);
+
blkid(8)
- add a new option (-r) that allows to print removable block devices that
@@ -36,6 +37,9 @@ wipefs
fdisk(s)
--------
+ * sfdisk rounds to cylinders is -uM (megabyte units) is specified, this is
+ pretty stupid feature. It has to round to sectors if -uS or -uM is specified.
+
* Sun label support is completely useless for large disks, it uses number of
cylinders from on-disk-label where the geometry is stored by int16 values.
It seems better to completely ignore this stuff from the label and always
diff --git a/disk-utils/blockdev.8 b/disk-utils/blockdev.8
index fa01da54..7176ffac 100644
--- a/disk-utils/blockdev.8
+++ b/disk-utils/blockdev.8
@@ -3,90 +3,82 @@
.\" Copyright 2007 Karel Zak <kzak@redhat.com>
.\"
.\" May be distributed under the GNU General Public License
-.TH BLOCKDEV 8 "Jun 2007" ""
+.TH BLOCKDEV 8 "Aug 2010" ""
.SH NAME
blockdev \- call block device ioctls from the command line
.SH SYNOPSIS
.B blockdev
-.RI [ options ]
-.I commands devices
+.RB [ \-q ]
+.RB [ \-v ]
+.IR command
+.RI [ command ...]
+.IR device
+.RI [ device ...]
.br
.B blockdev
.B \-\-report
-.RI [ devices ]
+.RI [ device ...]
.SH DESCRIPTION
The utility
.B blockdev
allows one to call block device ioctls from the command line.
.SH OPTIONS
-.TP
-.B \-V
+.IP "\fB\-V\fP"
Print version and exit.
-.TP
-.B \-q
+.IP "\fB\-q\fP"
Be quiet.
-.TP
-.B \-v
+.IP "\fB\-v\fP"
Be verbose.
-.TP
-.B \-\-report
-Print a report for
-.IR devices .
-Note that the partition StartSec is in 512-byte sectors.
+.IP "\fB\-\-report\fP"
+Print a report for the specified device. It is possible to give multiple
+devices. If none is given, all devices which appear in /proc/partitions are
+shown. Note that the partition StartSec is in 512-byte sectors.
.SH COMMANDS
-.TP
-.B \--setro
-Set read-only.
-.TP
-.B \--setrw
-Set read-write.
-.TP
-.B \--getro
-Get read-only. Print 1 if the device is read-only, 0 otherwise.
-.TP
-.B \--getss
-Print sectorsize in bytes - usually 512.
-.TP
-.B \--getbsz
+It is possible to give multiple devices and multiple commands.
+.IP "\fB\-\-flushbufs\fP"
+Flush buffers.
+.IP "\fB\-\-getalignoff\fP"
+Get alignment offset.
+.IP "\fB\-\-getbsz\fP"
Print blocksize in bytes.
-.TP
-.BI \--setbsz " N"
-Set blocksize to
-.I N
-bytes.
-.TP
-.B \--getsize
-Print device size in sectors (BLKGETSIZE). Deprecated in favor of the
-.B \--getsz
-option.
-.TP
-.B \--getsize64
-Print device size in bytes (BLKGETSIZE64)
-.TP
-.B \--getsz
-Get size in 512-byte sectors (BLKGETSIZE64 / 512).
-.TP
-.BI \--setra " N"
-Set readahead to
-.I N
-512-byte sectors.
-.TP
-.B \--getra
+.IP "\fB\-\-getdiscardzeroes\fP"
+Get discard zeroes support status.
+.IP "\fB\-\-getfra\fP"
+Get filesystem readahead in 512-byte sectors.
+.IP "\fB\-\-getiomin\fP"
+Get minimum I/O size.
+.IP "\fB\-\-getioopt\fP"
+Get optimal I/O size.
+.IP "\fB\-\-getmaxsect\fP"
+Get max sectors per request
+.IP "\fB\-\-getpbsz\fP"
+Get physical block (sector) size.
+.IP "\fB\-\-getra\fP"
Print readahead (in 512-byte sectors).
-.TP
-.BI \--setfra " N"
+.IP "\fB\-\-getro\fP"
+Get read-only. Print 1 if the device is read-only, 0 otherwise.
+.IP "\fB\-\-getsize64\fP"
+Print device size in bytes.
+.IP "\fB\-\-getsize\fP"
+Print device size (32-bit!) in sectors. Deprecated in favor of the --getsz option.
+.IP "\fB\-\-getss\fP"
+Print sectorsize in bytes - usually 512.
+.IP "\fB\-\-getsz\fP"
+Get size in 512-byte sectors.
+.IP "\fB\-\-rereadpt\fP"
+Seread partition table
+.IP "\fB\-\-setbsz\fP \fIbytes\fP"
+Set blocksize.
+.IP "\fB\-\-setfra\fP \fIsectors\fP"
Set filesystem readahead (same like --setra on 2.6 kernels).
-.TP
-.B \--getfra
-Get filesystem readahead.
-.TP
-.B \--flushbufs
-Flush buffers.
-.TP
-.B \--rereadpt
-Reread partition table.
+.IP "\fB\-\-setra\fP \fIsectors\fP"
+Set readahead (in 512-byte sectors).
+.IP "\fB\-\-setro\fP"
+Set read-only.
+.IP "\fB\-\-setrw\fP"
+Set read-write.
.SH AUTHOR
-blockdev was written by Andries E. Brouwer.
+blockdev was written by Andries E. Brouwer and rewritten by Karel Zak.
.SH AVAILABILITY
The blockdev command is part of the util-linux-ng package and is available from
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
diff --git a/disk-utils/blockdev.c b/disk-utils/blockdev.c
index cf594d12..27b1a0a2 100644
--- a/disk-utils/blockdev.c
+++ b/disk-utils/blockdev.c
@@ -75,6 +75,12 @@ struct bdc bdcms[] =
.argval = -1,
.help = N_("get read-only")
},{
+ IOCTL_ENTRY(BLKDISCARDZEROES),
+ .name = "--getdiscardzeroes",
+ .argtype = ARG_UINT,
+ .argval = -1,
+ .help = N_("get discard zeroes support status")
+ },{
IOCTL_ENTRY(BLKSSZGET),
.name = "--getss",
.argtype = ARG_INT,
@@ -103,7 +109,7 @@ struct bdc bdcms[] =
.name = "--getalignoff",
.argtype = ARG_INT,
.argval = -1,
- .help = N_("get alignment offset")
+ .help = N_("get alignment offset in bytes")
},{
IOCTL_ENTRY(BLKSECTGET),
.name = "--getmaxsect",
@@ -119,7 +125,7 @@ struct bdc bdcms[] =
},{
IOCTL_ENTRY(BLKBSZSET),
.name = "--setbsz",
- .argname = "BLOCKSIZE",
+ .argname = "<bytes>",
.argtype = ARG_INT,
.flags = FL_NORESULT,
.help = N_("set blocksize")
@@ -128,7 +134,7 @@ struct bdc bdcms[] =
.name = "--getsize",
.argtype = ARG_ULONG,
.argval = -1,
- .help = N_("get 32-bit sector count")
+ .help = N_("get 32-bit sector count (deprecated, use --getsz)")
},{
IOCTL_ENTRY(BLKGETSIZE64),
.name = "--getsize64",
@@ -138,7 +144,7 @@ struct bdc bdcms[] =
},{
IOCTL_ENTRY(BLKRASET),
.name = "--setra",
- .argname = "READAHEAD",
+ .argname = "<sectors>",
.argtype = ARG_INT,
.flags = FL_NOPTR | FL_NORESULT,
.help = N_("set readahead")
@@ -151,7 +157,7 @@ struct bdc bdcms[] =
},{
IOCTL_ENTRY(BLKFRASET),
.name = "--setfra",
- .argname = "FSREADAHEAD",
+ .argname = "<sectors>",
.argtype = ARG_INT,
.flags = FL_NOPTR | FL_NORESULT,
.help = N_("set filesystem readahead")
diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c
index e7955fe5..149a6166 100644
--- a/fdisk/cfdisk.c
+++ b/fdisk/cfdisk.c
@@ -197,7 +197,6 @@ int heads = 0;
int sectors = 0;
long long cylinders = 0;
int cylinder_size = 0; /* heads * sectors */
-long long total_size = 0; /* actual_size rounded down */
long long actual_size = 0; /* (in 512-byte sectors) - set using ioctl */
/* explicitly given user values */
int user_heads = 0, user_sectors = 0;
@@ -779,7 +778,7 @@ del_part(int i) {
if (i < num_parts - 1)
p_info[i].last_sector = p_info[i+1].first_sector - 1;
else
- p_info[i].last_sector = total_size - 1;
+ p_info[i].last_sector = actual_size - 1;
p_info[i].offset = 0;
p_info[i].flags = 0;
@@ -828,7 +827,7 @@ add_part(int num, int id, int flags, long long first, long long last,
return -1;
}
- if (first >= total_size) {
+ if (first >= actual_size) {
*errmsg = _("Partition begins after end-of-disk");
return -1;
}
@@ -838,11 +837,6 @@ add_part(int num, int id, int flags, long long first, long long last,
return -1;
}
- if (last >= total_size) {
- *errmsg = _("Partition ends in the final partial cylinder");
- return -1;
- }
-
for (i = 0; i < num_parts; i++) {
if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
pri++;
@@ -1535,8 +1529,7 @@ decide_on_geometry(void) {
if (user_cylinders > 0)
cylinders = user_cylinders;
- total_size = cylinder_size*cylinders;
- if (total_size > actual_size)
+ if (cylinder_size * cylinders > actual_size)
print_warning(_("You specified more cylinders than fit on disk"));
}
@@ -1544,7 +1537,7 @@ static void
clear_p_info(void) {
num_parts = 1;
p_info[0].first_sector = 0;
- p_info[0].last_sector = total_size - 1;
+ p_info[0].last_sector = actual_size - 1;
p_info[0].offset = 0;
p_info[0].flags = 0;
p_info[0].id = FREE_SPACE;
@@ -1629,7 +1622,7 @@ fill_p_info(void) {
((bs <= sectors) ? bs : 0), 1, &errmsg)) {
char *bad = _("Bad primary partition");
char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30);
- sprintf(msg, "%s %d: %s", bad, i, errmsg);
+ sprintf(msg, "%s %d: %s", bad, i + 1, errmsg);
fatal(msg, 4);
}
if (is_extended(buffer.p.part[i].sys_ind))
@@ -2327,7 +2320,7 @@ change_geometry(void) {
if (ret_val) {
long long disk_end;
- disk_end = total_size-1;
+ disk_end = actual_size-1;
if (p_info[num_parts-1].last_sector > disk_end) {
while (p_info[num_parts-1].first_sector > disk_end) {
diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index 6572c51d..68293213 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -180,6 +180,8 @@ static int type_open = O_RDWR;
*/
unsigned char *MBRbuffer;
+int MBRbuffer_changed;
+
/*
* per partition table entry data
*
@@ -217,12 +219,11 @@ unsigned long long sector_offset = 1, extended_offset = 0, sectors;
unsigned int heads,
cylinders,
sector_size = DEFAULT_SECTOR_SIZE,
- sector_factor = 1,
user_set_sector_size = 0,
units_per_sector = 1,
display_in_cyl_units = 0;
-unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */
+unsigned long long total_number_of_sectors; /* in logical sectors */
unsigned long grain = DEFAULT_SECTOR_SIZE,
io_size = DEFAULT_SECTOR_SIZE,
min_io_size = DEFAULT_SECTOR_SIZE,
@@ -658,7 +659,7 @@ static int
lba_is_aligned(unsigned long long lba)
{
unsigned int granularity = max(phy_sector_size, min_io_size);
- unsigned long long offset = (lba << 9) & (granularity - 1);
+ unsigned long long offset = (lba * sector_size) & (granularity - 1);
return !((granularity + alignment_offset - offset) & (granularity - 1));
}
@@ -770,7 +771,8 @@ void update_units(void)
static void
warn_limits(void) {
if (total_number_of_sectors > UINT_MAX && !nowarn) {
- int giga = (total_number_of_sectors << 9) / 1000000000;
+ unsigned long long bytes = total_number_of_sectors * sector_size;
+ int giga = bytes / 1000000000;
int hectogiga = (giga + 50) / 100;
fprintf(stderr, _("\n"
@@ -779,7 +781,7 @@ warn_limits(void) {
"larger than (%llu bytes) for %d-byte sectors. Use parted(1) and GUID \n"
"partition table format (GPT).\n\n"),
hectogiga / 10, hectogiga % 10,
- total_number_of_sectors << 9,
+ bytes,
(unsigned long long ) UINT_MAX * sector_size,
sector_size);
}
@@ -934,6 +936,7 @@ dos_set_mbr_id(void) {
return;
dos_write_mbr_id(MBRbuffer, new_id);
+ MBRbuffer_changed = 1;
dos_print_mbr_id();
}
@@ -1119,10 +1122,9 @@ update_sector_offset(void)
void
get_geometry(int fd, struct geom *g) {
- unsigned long long llcyls;
+ unsigned long long llcyls, nsects = 0;
get_topology(fd);
- sector_factor = sector_size / 512;
guess_device_type(fd);
heads = cylinders = sectors = 0;
kern_heads = kern_sectors = 0;
@@ -1138,12 +1140,13 @@ get_geometry(int fd, struct geom *g) {
pt_sectors ? pt_sectors :
kern_sectors ? kern_sectors : 63;
- if (blkdev_get_sectors(fd, &total_number_of_sectors) == -1)
- total_number_of_sectors = 0;
+ /* get number of 512-byte sectors, and convert it the real sectors */
+ if (blkdev_get_sectors(fd, &nsects) == 0)
+ total_number_of_sectors = (nsects / (sector_size >> 9));
update_sector_offset();
- llcyls = total_number_of_sectors / (heads * sectors * sector_factor);
+ llcyls = total_number_of_sectors / (heads * sectors);
cylinders = llcyls;
if (cylinders != llcyls) /* truncated? */
cylinders = ~0;
@@ -1886,7 +1889,7 @@ check_alignment(unsigned long long lba, int partition)
static void
list_disk_geometry(void) {
- long long bytes = (total_number_of_sectors << 9);
+ unsigned long long bytes = total_number_of_sectors * sector_size;
long megabytes = bytes/1000000;
if (megabytes < 10000)
@@ -1894,14 +1897,13 @@ list_disk_geometry(void) {
disk_device, megabytes, bytes);
else {
long hectomega = (megabytes + 50) / 100;
- printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
+ printf(_("\nDisk %s: %ld.%ld GB, %llu bytes\n"),
disk_device, hectomega / 10, hectomega % 10, bytes);
}
printf(_("%d heads, %llu sectors/track, %d cylinders"),
heads, sectors, cylinders);
if (units_per_sector == 1)
- printf(_(", total %llu sectors"),
- total_number_of_sectors / sector_factor);
+ printf(_(", total %llu sectors"), total_number_of_sectors);
printf("\n");
printf(_("Units = %s of %d * %d = %d bytes\n"),
str_units(PLURAL),
@@ -2210,7 +2212,7 @@ static void
verify(void) {
int i, j;
unsigned long long total = 1;
- unsigned long long n_sectors = (total_number_of_sectors / sector_factor);
+ unsigned long long n_sectors = total_number_of_sectors;
unsigned long long first[partitions], last[partitions];
struct partition *p;
@@ -2324,7 +2326,7 @@ add_partition(int n, int sys) {
if (display_in_cyl_units || !total_number_of_sectors)
llimit = heads * sectors * cylinders - 1;
else
- llimit = (total_number_of_sectors / sector_factor) - 1;
+ llimit = total_number_of_sectors - 1;
limit = llimit;
if (limit != llimit)
limit = 0x7fffffff;
@@ -2553,10 +2555,18 @@ write_table(void) {
int i;
if (dos_label) {
- for (i=0; i<3; i++)
- if (ptes[i].changed)
- ptes[3].changed = 1;
- for (i = 3; i < partitions; i++) {
+ /* MBR (primary partitions) */
+ if (!MBRbuffer_changed) {
+ for (i = 0; i < 4; i++)
+ if (ptes[i].changed)
+ MBRbuffer_changed = 1;
+ }
+ if (MBRbuffer_changed) {
+ write_part_table_flag(MBRbuffer);
+ write_sector(fd, 0, MBRbuffer);
+ }
+ /* EBR (logical partitions) */
+ for (i = 4; i < partitions; i++) {
struct pte *pe = &ptes[i];
if (pe->changed) {
diff --git a/fsck/Makefile.am b/fsck/Makefile.am
index b0949e25..22566d19 100644
--- a/fsck/Makefile.am
+++ b/fsck/Makefile.am
@@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am
sbin_PROGRAMS = fsck
dist_man_MANS = fsck.8
-fsck_SOURCES = base_device.c fsck.c fsck.h $(top_srcdir)/lib/ismounted.c \
+fsck_SOURCES = fsck.c fsck.h $(top_srcdir)/lib/ismounted.c \
$(top_srcdir)/lib/fsprobe.c $(top_srcdir)/lib/canonicalize.c
fsck_LDADD =
fsck_CFLAGS = $(AM_CFLAGS)
diff --git a/fsck/base_device.c b/fsck/base_device.c
deleted file mode 100644
index aad2ba05..00000000
--- a/fsck/base_device.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * base_device.c
- *
- * Return the "base device" given a particular device; this is used to
- * assure that we only fsck one partition on a particular drive at any
- * one time. Otherwise, the disk heads will be seeking all over the
- * place. If the base device can not be determined, return NULL.
- *
- * The base_device() function returns an allocated string which must
- * be freed.
- *
- * Written by Theodore Ts'o, <tytso@mit.edu>
- *
- * Copyright (C) 2000 Theodore Ts'o.
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
- */
-#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <ctype.h>
-#include <string.h>
-
-#include "fsck.h"
-
-/*
- * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
- * pathames.
- */
-static const char *devfs_hier[] = {
- "host", "bus", "target", "lun", 0
-};
-
-char *base_device(const char *device)
-{
- char *str, *cp;
- const char **hier, *disk;
- int len;
-
- str = malloc(strlen(device)+1);
- if (!str)
- return NULL;
- strcpy(str, device);
- cp = str;
-
- /* Skip over /dev/; if it's not present, give up. */
- if (strncmp(cp, "/dev/", 5) != 0)
- goto errout;
- cp += 5;
-
- /* Skip over /dev/dsk/... */
- if (strncmp(cp, "dsk/", 4) == 0)
- cp += 4;
-
- /*
- * For md devices, we treat them all as if they were all
- * on one disk, since we don't know how to parallelize them.
- */
- if (cp[0] == 'm' && cp[1] == 'd') {
- *(cp+2) = 0;
- return str;
- }
-
- /* Handle DAC 960 devices */
- if (strncmp(cp, "rd/", 3) == 0) {
- cp += 3;
- if (cp[0] != 'c' || cp[2] != 'd' ||
- !isdigit(cp[1]) || !isdigit(cp[3]))
- goto errout;
- *(cp+4) = 0;
- return str;
- }
-
- /* Now let's handle /dev/hd* and /dev/sd* devices.... */
- if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
- cp += 2;
- /* If there's a single number after /dev/hd, skip it */
- if (isdigit(*cp))
- cp++;
- /* What follows must be an alpha char, or give up */
- if (!isalpha(*cp))
- goto errout;
- *(cp + 1) = 0;
- return str;
- }
-
- /* Now let's handle devfs (ugh) names */
- len = 0;
- if (strncmp(cp, "ide/", 4) == 0)
- len = 4;
- if (strncmp(cp, "scsi/", 5) == 0)
- len = 5;
- if (len) {
- cp += len;
- /*
- * Now we proceed down the expected devfs hierarchy.
- * i.e., .../host1/bus2/target3/lun4/...
- * If we don't find the expected token, followed by
- * some number of digits at each level, abort.
- */
- for (hier = devfs_hier; *hier; hier++) {
- len = strlen(*hier);
- if (strncmp(cp, *hier, len) != 0)
- goto errout;
- cp += len;
- while (*cp != '/' && *cp != 0) {
- if (!isdigit(*cp))
- goto errout;
- cp++;
- }
- cp++;
- }
- *(cp - 1) = 0;
- return str;
- }
-
- /* Now handle devfs /dev/disc or /dev/disk names */
- disk = 0;
- if (strncmp(cp, "discs/", 6) == 0)
- disk = "disc";
- else if (strncmp(cp, "disks/", 6) == 0)
- disk = "disk";
- if (disk) {
- cp += 6;
- if (strncmp(cp, disk, 4) != 0)
- goto errout;
- cp += 4;
- while (*cp != '/' && *cp != 0) {
- if (!isdigit(*cp))
- goto errout;
- cp++;
- }
- *cp = 0;
- return str;
- }
-
-errout:
- free(str);
- return NULL;
-}
-
-#ifdef DEBUG
-int main(int argc, char** argv)
-{
- const char *base;
- char buf[256], *cp;
-
- while (1) {
- if (fgets(buf, sizeof(buf), stdin) == NULL)
- break;
- cp = strchr(buf, '\n');
- if (cp)
- *cp = 0;
- cp = strchr(buf, '\t');
- if (cp)
- *cp = 0;
- base = base_device(buf);
- printf("%s\t%s\n", buf, base ? base : "NONE");
- }
- exit(0);
-}
-#endif
diff --git a/fsck/fsck.8 b/fsck/fsck.8
index 027fb3fe..9cf80785 100644
--- a/fsck/fsck.8
+++ b/fsck/fsck.8
@@ -200,6 +200,11 @@ If there are multiple filesystems with the same pass number,
fsck will attempt to check them in parallel, although it will avoid running
multiple filesystem checks on the same physical disk.
.sp
+.B fsck
+does not check stacked devices (RAIDs, dm-crypt, ...) in parallel with any other
+device. See below for FSCK_FORCE_ALL_PARALLEL setting. The /sys filesystem is
+used to detemine dependencies between devices.
+.sp
Hence, a very common configuration in
.I /etc/fstab
files is to set the root filesystem to have a
@@ -366,10 +371,10 @@ program's behavior is affected by the following environment variables:
.B FSCK_FORCE_ALL_PARALLEL
If this environment variable is set,
.B fsck
-will attempt to run all of the specified filesystems in parallel,
-regardless of whether the filesystems appear to be on the same
-device. (This is useful for RAID systems or high-end storage systems
-such as those sold by companies such as IBM or EMC.)
+will attempt to run all of the specified filesystems in parallel, regardless of
+whether the filesystems appear to be on the same device. (This is useful for
+RAID systems or high-end storage systems such as those sold by companies such
+as IBM or EMC.) Note that the fs_passno value is still used.
.TP
.B FSCK_MAX_INST
This environment variable will limit the maximum number of file system
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 7577eff1..e7526f9e 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -42,6 +42,8 @@
#include <errno.h>
#include <malloc.h>
#include <signal.h>
+#include <dirent.h>
+#include <blkid.h>
#include "fsprobe.h"
@@ -217,8 +219,6 @@ static void parse_escape(char *word)
static void free_instance(struct fsck_instance *i)
{
free(i->prog);
- free(i->device);
- free(i->base_device);
free(i);
return;
}
@@ -240,6 +240,8 @@ static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
fs->passno = passno;
fs->flags = 0;
fs->next = NULL;
+ fs->disk = 0;
+ fs->stacked = 0;
if (!filesys_info)
filesys_info = fs;
@@ -414,8 +416,7 @@ static int progress_active(NOARGS)
* Execute a particular fsck program, and link it into the list of
* child processes we are waiting for.
*/
-static int execute(const char *type, const char *device, const char *mntpt,
- int interactive)
+static int execute(const char *type, struct fs_info *fs, int interactive)
{
char *s, *argv[80], prog[80];
int argc, i;
@@ -452,7 +453,7 @@ static int execute(const char *type, const char *device, const char *mntpt,
}
}
- argv[argc++] = string_copy(device);
+ argv[argc++] = string_copy(fs->device);
argv[argc] = 0;
s = find_fsck(prog);
@@ -464,7 +465,7 @@ static int execute(const char *type, const char *device, const char *mntpt,
if (verbose || noexecute) {
printf("[%s (%d) -- %s] ", s, num_running,
- mntpt ? mntpt : device);
+ fs->mountpt ? fs->mountpt : fs->device);
for (i=0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
@@ -492,9 +493,8 @@ static int execute(const char *type, const char *device, const char *mntpt,
inst->pid = pid;
inst->prog = string_copy(prog);
inst->type = string_copy(type);
- inst->device = string_copy(device);
- inst->base_device = base_device(device);
inst->start_time = time(0);
+ inst->fs = fs;
inst->next = NULL;
/*
@@ -597,12 +597,12 @@ static struct fsck_instance *wait_one(int flags)
} else {
printf(_("Warning... %s for device %s exited "
"with signal %d.\n"),
- inst->prog, inst->device, sig);
+ inst->prog, inst->fs->device, sig);
status = EXIT_ERROR;
}
} else {
printf(_("%s %s: status is %x, should never happen.\n"),
- inst->prog, inst->device, status);
+ inst->prog, inst->fs->device, status);
status = EXIT_ERROR;
}
inst->exit_status = status;
@@ -641,7 +641,7 @@ ret_inst:
instance_list = inst->next;
if (verbose > 1)
printf(_("Finished with %s (exit status %d)\n"),
- inst->device, inst->exit_status);
+ inst->fs->device, inst->exit_status);
num_running--;
return inst;
}
@@ -698,7 +698,7 @@ static void fsck_device(struct fs_info *fs, int interactive)
type = DEFAULT_FSTYPE;
num_running++;
- retval = execute(type, fs->device, fs->mountpt, interactive);
+ retval = execute(type, fs, interactive);
if (retval) {
fprintf(stderr, _("%s: Error %d while executing fsck.%s "
"for %s\n"), progname, retval, type, fs->device);
@@ -924,40 +924,75 @@ static int ignore(struct fs_info *fs)
return 0;
}
+static int count_slaves(dev_t disk)
+{
+ DIR *dir;
+ struct dirent *dp;
+ char dirname[PATH_MAX];
+ int count = 0;
+
+ snprintf(dirname, sizeof(dirname),
+ "/sys/dev/block/%u:%u/slaves/",
+ major(disk), minor(disk));
+
+ if (!(dir = opendir(dirname)))
+ return -1;
+
+ while ((dp = readdir(dir)) != 0) {
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
+ continue;
+#endif
+ if (dp->d_name[0] == '.' &&
+ ((dp->d_name[1] == 0) ||
+ ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
+ continue;
+
+ count++;
+ }
+ closedir(dir);
+ return count;
+}
+
/*
* Returns TRUE if a partition on the same disk is already being
* checked.
*/
-static int device_already_active(char *device)
+static int disk_already_active(struct fs_info *fs)
{
struct fsck_instance *inst;
- char *base;
if (force_all_parallel)
return 0;
-#ifdef BASE_MD
- /* Don't check a soft raid disk with any other disk */
- if (instance_list &&
- (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
- !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
+ if (instance_list && instance_list->fs->stacked)
+ /* any instance for a stacked device is already running */
return 1;
-#endif
- base = base_device(device);
+ if (!fs->disk) {
+ struct stat st;
+ dev_t disk;
+
+ if (!stat(fs->device, &st) &&
+ !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk)) {
+ fs->disk = disk;
+ fs->stacked = count_slaves(disk);
+ }
+ }
+
/*
* If we don't know the base device, assume that the device is
* already active if there are any fsck instances running.
+ *
+ * Don't check a stacked device with any other disk too.
*/
- if (!base)
+ if (!fs->disk || fs->stacked)
return (instance_list != 0);
+
for (inst = instance_list; inst; inst = inst->next) {
- if (!inst->base_device || !strcmp(base, inst->base_device)) {
- free(base);
+ if (!inst->fs->disk || fs->disk == inst->fs->disk)
return 1;
- }
}
- free(base);
return 0;
}
@@ -1038,7 +1073,7 @@ static int check_all(NOARGS)
* already been spawned, then we need to defer
* this to another pass.
*/
- if (device_already_active(fs->device)) {
+ if (disk_already_active(fs)) {
pass_done = 0;
continue;
}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 45b78446..d212622f 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -44,6 +44,8 @@ struct fs_info {
int freq;
int passno;
int flags;
+ dev_t disk;
+ int stacked;
struct fs_info *next;
};
@@ -60,8 +62,7 @@ struct fsck_instance {
time_t start_time;
char * prog;
char * type;
- char * device;
- char * base_device;
+ struct fs_info *fs;
struct fsck_instance *next;
};
diff --git a/include/blkdev.h b/include/blkdev.h
index 0eea01cd..5344a2ba 100644
--- a/include/blkdev.h
+++ b/include/blkdev.h
@@ -8,46 +8,57 @@
#define DEFAULT_SECTOR_SIZE 512
-#if !defined(BLKROSET) && defined(__linux__)
-
-#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
-#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
-#define BLKRRPART _IO(0x12,95) /* re-read partition table */
-#define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
-#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
-#define BLKRASET _IO(0x12,98) /* set read ahead for block device */
-#define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
-#define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
-#define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
-#define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
-#define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
-#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
+#ifdef __linux__
+/* very basic ioclts, should be available everywhere */
+# ifndef BLKROSET
+# define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
+# define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
+# define BLKRRPART _IO(0x12,95) /* re-read partition table */
+# define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
+# define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
+# define BLKRASET _IO(0x12,98) /* set read ahead for block device */
+# define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
+# define BLKFRASET _IO(0x12,100) /* set filesystem (mm/filemap.c) read-ahead */
+# define BLKFRAGET _IO(0x12,101) /* get filesystem (mm/filemap.c) read-ahead */
+# define BLKSECTSET _IO(0x12,102) /* set max sectors per request (ll_rw_blk.c) */
+# define BLKSECTGET _IO(0x12,103) /* get max sectors per request (ll_rw_blk.c) */
+# define BLKSSZGET _IO(0x12,104) /* get block device sector size */
/* ioctls introduced in 2.2.16, removed in 2.5.58 */
-#define BLKELVGET _IOR(0x12,106,size_t) /* elevator get */
-#define BLKELVSET _IOW(0x12,107,size_t) /* elevator set */
+# define BLKELVGET _IOR(0x12,106,size_t) /* elevator get */
+# define BLKELVSET _IOW(0x12,107,size_t) /* elevator set */
-#define BLKBSZGET _IOR(0x12,112,size_t)
-#define BLKBSZSET _IOW(0x12,113,size_t)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
+# define BLKBSZGET _IOR(0x12,112,size_t)
+# define BLKBSZSET _IOW(0x12,113,size_t)
+# endif /* !BLKROSET */
-#endif /* BLKROSET && __linux__ */
+# ifndef BLKGETSIZE64
+# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
+# endif
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif
+/* block device topology ioctls, introduced in 2.6.32 (commit ac481c20) */
+# ifndef BLKIOMIN
+# define BLKIOMIN _IO(0x12,120)
+# define BLKIOOPT _IO(0x12,121)
+# define BLKALIGNOFF _IO(0x12,122)
+# define BLKPBSZGET _IO(0x12,123)
+# endif
-/* block device topology ioctls, introduced in 2.6.32 */
-#ifndef BLKIOMIN
-#define BLKIOMIN _IO(0x12,120)
-#define BLKIOOPT _IO(0x12,121)
-#define BLKALIGNOFF _IO(0x12,122)
-#define BLKPBSZGET _IO(0x12,123)
-#endif
+/* discard zeroes support, introduced in 2.6.33 (commit 98262f27) */
+# ifndef BLKDISCARDZEROES
+# define BLKDISCARDZEROES _IO(0x12,124)
+# endif
+
+/* filesystem freeze, introduced in 2.6.29 (commit fcccf502) */
+# ifndef FIFREEZE
+# define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+# define FITHAW _IOWR('X', 120, int) /* Thaw */
+# endif
-#ifndef FIFREEZE
-#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
-#define FITHAW _IOWR('X', 120, int) /* Thaw */
+#endif /* __linux */
+
+#ifdef APPLE_DARWIN
+# define BLKGETSIZE DKIOCGETBLOCKCOUNT32
#endif
#ifndef HDIO_GETGEO
diff --git a/lib/blkdev.c b/lib/blkdev.c
index 7d00324d..67c4a1ac 100644
--- a/lib/blkdev.c
+++ b/lib/blkdev.c
@@ -104,7 +104,7 @@ blkdev_get_size(int fd, unsigned long long *bytes)
#ifdef DIOCGMEDIASIZE
/* FreeBSD */
if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
- return 0
+ return 0;
#endif
#ifdef FDGETPRM
diff --git a/login-utils/agetty.8 b/login-utils/agetty.8
index 87613747..084086fd 100644
--- a/login-utils/agetty.8
+++ b/login-utils/agetty.8
@@ -3,7 +3,7 @@
agetty \- alternative Linux getty
.SH SYNOPSIS
-.BR "agetty " [\-8ihLmnUw]
+.BR "agetty " [\-c8ihLmnsUw]
.RI "[-f " issue_file ]
.RI "[-l " login_program ]
.RI "[-I " init ]
@@ -12,16 +12,6 @@ agetty \- alternative Linux getty
.I port
.I baud_rate,...
.RI [ term ]
-.br
-.BR "agetty " [\-8ihLmnw]
-.RI "[-f " issue_file ]
-.RI "[-l " login_program ]
-.RI "[-I " init ]
-.RI "[-t " timeout ]
-.RI "[-H " login_host ]
-.I baud_rate,...
-.I port
-.RI [ term ]
.SH DESCRIPTION
.ad
@@ -92,6 +82,10 @@ whatever init(8) may have set, and is inherited by login and the shell.
.fi
.ad
.TP
+\-c
+Don't reset terminal cflags (control modes). See \fItermios(3)\fP for more
+details.
+.TP
\-8
Assume that the tty is 8-bit clean, hence disable parity detection.
.TP
@@ -163,6 +157,10 @@ Force the line to be a local line with no need for carrier detect. This can
be useful when you have a locally attached terminal where the serial line
does not set the carrier detect signal.
.TP
+\-s
+Try to keep the existing baud rate. The baud rates from
+the command line are used when agetty receives a BREAK character.
+.TP
\-U
Turn on support for detecting an uppercase only terminal. This setting will
detect a login name containing only capitals as indicating an uppercase
diff --git a/login-utils/agetty.c b/login-utils/agetty.c
index a59943f5..3d544fb9 100644
--- a/login-utils/agetty.c
+++ b/login-utils/agetty.c
@@ -137,6 +137,8 @@ struct options {
#define F_CUSTISSUE (1<<6) /* give alternative issue file */
#define F_NOPROMPT (1<<7) /* don't ask for login name! */
#define F_LCUC (1<<8) /* Support for *LCUC stty modes */
+#define F_KEEPSPEED (1<<9) /* Follow baud rate from kernel */
+#define F_KEEPCFLAGS (1<<10) /* Reuse c_cflags setup from kernel */
/* Storage for things detected while the login name was read. */
@@ -207,7 +209,7 @@ void parse_args P_((int argc, char **argv, struct options *op));
void parse_speeds P_((struct options *op, char *arg));
void update_utmp P_((char *line));
void open_tty P_((char *tty, struct termios *tp, int local));
-void termio_init P_((struct termios *tp, int speed, struct options *op));
+void termio_init P_((struct termios *tp, struct options *op));
void auto_baud P_((struct termios *tp));
void do_prompt P_((struct options *op, struct termios *tp));
void next_speed P_((struct termios *tp, struct options *op));
@@ -301,7 +303,7 @@ main(argc, argv)
tcsetpgrp(0, getpid());
/* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
debug("calling termio_init\n");
- termio_init(&termios, options.speeds[FIRST_SPEED], &options);
+ termio_init(&termios, &options);
/* write the modem init string and DON'T flush the buffers */
if (options.flags & F_INITSTRING) {
@@ -377,8 +379,11 @@ parse_args(argc, argv, op)
extern int optind; /* getopt */
int c;
- while (isascii(c = getopt(argc, argv, "8I:LH:f:hil:mt:wUn"))) {
+ while (isascii(c = getopt(argc, argv, "8cI:LH:f:hil:mst:wUn"))) {
switch (c) {
+ case 'c':
+ op->flags |= F_KEEPCFLAGS;
+ break;
case '8':
op->eightbits = 1;
break;
@@ -447,6 +452,9 @@ parse_args(argc, argv, op)
case 'n':
op->flags |= F_NOPROMPT;
break;
+ case 's':
+ op->flags |= F_KEEPSPEED; /* keep kernel defined speed */
+ break;
case 't': /* time out */
if ((op->timeout = atoi(optarg)) <= 0)
error(_("bad timeout value: %s"), optarg);
@@ -702,9 +710,8 @@ char gbuf[1024];
char area[1024];
void
-termio_init(tp, speed, op)
+termio_init(tp, op)
struct termios *tp;
- int speed;
struct options *op;
{
@@ -717,9 +724,13 @@ termio_init(tp, speed, op)
/* flush input and output queues, important for modems! */
(void) tcflush(0, TCIOFLUSH);
- tp->c_cflag = CS8 | HUPCL | CREAD;
- cfsetispeed(tp, speed);
- cfsetospeed(tp, speed);
+ if (!(op->flags & F_KEEPCFLAGS))
+ tp->c_cflag = CS8 | HUPCL | CREAD | (tp->c_cflag & CLOCAL);
+
+ if (!(op->flags & F_KEEPSPEED)) {
+ cfsetispeed(tp, op->speeds[FIRST_SPEED]);
+ cfsetospeed(tp, op->speeds[FIRST_SPEED]);
+ }
if (op->flags & F_LOCAL) {
tp->c_cflag |= CLOCAL;
}
@@ -1214,7 +1225,7 @@ bcode(s)
void
usage()
{
- fprintf(stderr, _("Usage: %s [-8hiLmUw] [-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);
+ fprintf(stderr, _("Usage: %s [-8hiLmsUw] [-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);
}
diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c
index 4138480f..21a3566c 100644
--- a/misc-utils/findmnt.c
+++ b/misc-utils/findmnt.c
@@ -417,7 +417,8 @@ static mnt_fs *get_next_fs(mnt_tab *tb, mnt_iter *itr)
*/
fs = mnt_tab_find_source(tb, get_match(COL_SOURCE),
mnt_iter_get_direction(itr));
- if (!fs)
+
+ if (!fs && !(flags & FL_NOSWAPMATCH))
fs = mnt_tab_find_target(tb, get_match(COL_SOURCE),
mnt_iter_get_direction(itr));
} else {
diff --git a/mount/fstab.5 b/mount/fstab.5
index 1c5cdca9..c10490a4 100644
--- a/mount/fstab.5
+++ b/mount/fstab.5
@@ -40,11 +40,11 @@
.\" Tue Jun 15 20:02:18 1999: added LABEL and UUID
.\" Sat Jul 14 2001: Michael K. Johnson <johnsonm@redhat.com> added -O
.\"
-.TH FSTAB 5 "15 June 1999" "Linux 2.2" "Linux Programmer's Manual"
+.TH FSTAB 5 "August 2010" "Linux 2.6" "Linux Programmer's Manual"
.SH NAME
fstab \- static information about the filesystems
.SH SYNOPSIS
-.B #include <fstab.h>
+.B /etc/fstab
.SH DESCRIPTION
The file
.B fstab
@@ -64,9 +64,10 @@ sequentially iterate through
.B fstab
doing their thing.
-The first field,
-.RI ( fs_spec ),
-describes the block special device or
+.B The first field
+.RI ( fs_spec ).
+.RS
+This field describes the block special device or
remote filesystem to be mounted.
.LP
For ordinary mounts it will hold (a link to) a block special
@@ -86,16 +87,20 @@ writing LABEL=<label> or UUID=<uuid>,
e.g., `LABEL=Boot' or `UUID=3e6be9de\%-8139\%-11d1\%-9106\%-a43f08d823a6'.
This will make the system more robust: adding or removing a SCSI disk
changes the disk device name but not the filesystem volume label.
+.RE
-The second field,
-.RI ( fs_file ),
-describes the mount point for the filesystem. For swap partitions, this
+.B The second field
+.RI ( fs_file ).
+.RS
+This field describes the mount point for the filesystem. For swap partitions, this
field should be specified as `none'. If the name of the mount point
contains spaces these can be escaped as `\\040'.
+.RE
-The third field,
-.RI ( fs_vfstype ),
-describes the type of the filesystem. Linux supports lots
+.B The third field
+.RI ( fs_vfstype ).
+.RS
+This field describes the type of the filesystem. Linux supports lots
of filesystem types, such as
.IR adfs ,
.IR affs ,
@@ -131,8 +136,10 @@ of filesystem types, such as
.IR xfs ,
and possibly others. For more details, see
.BR mount (8).
+
For the filesystems currently supported by the running kernel, see
.IR /proc/filesystems .
+
An entry
.I swap
denotes a file or partition to be used
@@ -146,38 +153,62 @@ An entry
.I none
is useful for bind or move mounts.
-The fourth field,
-.RI ( fs_mntops ),
-describes the mount options associated with the filesystem.
+.BR mount (8)
+and
+.BR umount (8)
+support filesystem
+.IR subtypes .
+The subtype is defined by '.subtype' suffix. For
+example 'fuse.sshfs'. It's recommended to use subtype notation rather than add
+any prefix to the first fstab field (for example 'sshfs#example.com' is
+depreacated).
+.RE
+
+.B The fourth field
+.RI ( fs_mntops ).
+.RS
+This field describes the mount options associated with the filesystem.
It is formatted as a comma separated list of options. It contains at least
the type of mount plus any additional options appropriate to the filesystem
-type. For documentation on the available options for non-nfs file systems,
-see
-.BR mount (8).
-For documentation on all nfs-specific options have a look at
-.BR nfs (5).
-Common for all types of file system are the options ``noauto''
-(do not mount when "mount -a" is given, e.g., at boot time), ``user''
-(allow a user to mount), and ``owner''
-(allow device owner to mount), and ``comment''
-(e.g., for use by fstab-maintaining programs).
-The ``owner'' and ``comment'' options are Linux-specific.
-For more details, see
+type. For documentation on the available options, see
.BR mount (8).
+Basic file system independent options are:
+.TP
+.B defaults
+use default options: rw, suid, dev, exec, auto, nouser, and async.
+.TP
+.B noauto
+do not mount when "mount -a" is given (e.g., at boot time)
+.TP
+.B user
+allow a user to mount
+.TP
+.B owner
+allow device owner to mount
+.TP
+.B comment
+for use by fstab-maintaining programs
+.TP
+.B nofail
+do not report errors for this device if it does not exist.
+.RE
-The fifth field,
-.RI ( fs_freq ),
-is used for these filesystems by the
+.B The fifth field
+.RI ( fs_freq ).
+.RS
+This field is used for these filesystems by the
.BR dump (8)
command to determine which filesystems need to be dumped. If the fifth
field is not present, a value of zero is returned and
.B dump
will assume that the filesystem does not need to be dumped.
+.RE
-The sixth field,
-.RI ( fs_passno ),
-is used by the
+.B The sixth field
+.RI ( fs_passno ).
+.RS
+This field is used by the
.BR fsck (8)
program to determine the order in which filesystem checks are done at
reboot time. The root filesystem should be specified with a
@@ -190,19 +221,23 @@ parallelism available in the hardware. If the sixth field is not present
or zero, a value of zero is returned and
.B fsck
will assume that the filesystem does not need to be checked.
+.RE
The proper way to read records from
.B fstab
is to use the routines
.BR getmntent (3).
.SH FILES
-.I /etc/fstab
+.IR /etc/fstab ,
+.I <fstab.h>
.SH "SEE ALSO"
-.BR getmntent (3),
.BR mount (8),
.BR swapon (8),
.BR fs (5),
-.BR nfs (5)
+.BR nfs (5),
+.BR xfs (5),
+.BR proc (5),
+.BR getmntent (3)
.SH HISTORY
The ancestor of this
.B fstab
diff --git a/mount/fstab.c b/mount/fstab.c
index 97d64a2c..bfb2e5d3 100644
--- a/mount/fstab.c
+++ b/mount/fstab.c
@@ -216,6 +216,24 @@ getmntfile (const char *name) {
}
/*
+ * Given the name NAME, and the place MCPREV we found it last time,
+ * try to find it in mtab.
+ */
+struct mntentchn *
+getmntfilebackward (const char *name, struct mntentchn *mcprev) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = mtab_head();
+ if (!mcprev)
+ mcprev = mc0;
+ for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+ if (streq(mc->m.mnt_dir, name) ||
+ streq(mc->m.mnt_fsname, name))
+ return mc;
+ return NULL;
+}
+
+/*
* Given the directory name NAME, and the place MCPREV we found it last time,
* try to find more occurrences.
*/
diff --git a/mount/fstab.h b/mount/fstab.h
index 38f7bab9..e9855064 100644
--- a/mount/fstab.h
+++ b/mount/fstab.h
@@ -15,6 +15,7 @@ struct mntentchn {
struct mntentchn *mtab_head (void);
struct mntentchn *getmntfile (const char *name);
+struct mntentchn *getmntfilebackward (const char *name, struct mntentchn *mcprev);
struct mntentchn *getmntoptfile (const char *file);
struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
diff --git a/mount/lomount.c b/mount/lomount.c
index db6d5326..00107d67 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -259,11 +259,16 @@ loop_scandir(const char *dirname, int **ary, int hasprefix)
if (n == -1 || n < NLOOPS_DEFAULT)
continue;
if (count + 1 > arylen) {
+ int *tmp;
+
arylen += 1;
- *ary = *ary ? realloc(*ary, arylen * sizeof(int)) :
- malloc(arylen * sizeof(int));
- if (!*ary)
+
+ tmp = realloc(*ary, arylen * sizeof(int));
+ if (!tmp) {
+ free(*ary);
return -1;
+ }
+ *ary = tmp;
}
(*ary)[count++] = n;
}
@@ -953,8 +958,8 @@ find_unused_loop_device (void) {
#include "strtosize.h"
static void
-usage(void) {
- fprintf(stderr, _("\nUsage:\n"
+usage(FILE *f) {
+ fprintf(f, _("\nUsage:\n"
" %1$s loop_device give info\n"
" %1$s -a | --all list all used\n"
" %1$s -d | --detach <loopdev> [<loopdev> ...] delete\n"
@@ -964,7 +969,7 @@ usage(void) {
" %1$s [ options ] {-f|--find|loopdev} <file> setup\n"),
progname);
- fprintf(stderr, _("\nOptions:\n"
+ fprintf(f, _("\nOptions:\n"
" -e | --encryption <type> enable data encryption with specified <name/num>\n"
" -h | --help this help\n"
" -o | --offset <num> start at offset <num> into file\n"
@@ -979,7 +984,8 @@ usage(void) {
" key size. Key sizes < 128 are generally not\n"
" recommended\n"
" -v | --verbose verbose mode\n\n"));
- exit(1);
+
+ exit(f == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
@@ -1048,6 +1054,9 @@ main(int argc, char **argv) {
case 'f':
find = 1;
break;
+ case 'h':
+ usage(stdout);
+ break;
case 'j':
assoc = optarg;
case 'k':
@@ -1074,42 +1083,42 @@ main(int argc, char **argv) {
break;
default:
- usage();
+ usage(stderr);
}
}
if (argc == 1) {
- usage();
+ usage(stderr);
} else if (delete) {
if (argc < optind+1 || encryption || offset || sizelimit ||
capacity || find || all || showdev || assoc || ro)
- usage();
+ usage(stderr);
} else if (find) {
if (capacity || all || assoc || argc < optind || argc > optind+1)
- usage();
+ usage(stderr);
} else if (all) {
if (argc > 2)
- usage();
+ usage(stderr);
} else if (assoc) {
if (capacity || encryption || showdev || passfd || ro)
- usage();
+ usage(stderr);
} else if (capacity) {
if (argc != optind + 1 || encryption || offset || sizelimit ||
showdev || ro)
- usage();
+ usage(stderr);
} else {
if (argc < optind+1 || argc > optind+2)
- usage();
+ usage(stderr);
}
if (offset && strtosize(offset, &off)) {
error(_("%s: invalid offset '%s' specified"), progname, offset);
- usage();
+ usage(stderr);
}
if (sizelimit && strtosize(sizelimit, &slimit)) {
error(_("%s: invalid sizelimit '%s' specified"),
progname, sizelimit);
- usage();
+ usage(stderr);
}
if (all)
@@ -1144,9 +1153,9 @@ main(int argc, char **argv) {
res = show_loop(device);
else {
if (passfd && sscanf(passfd, "%d", &pfd) != 1)
- usage();
+ usage(stderr);
if (keysize && sscanf(keysize,"%d",&keysz) != 1)
- usage();
+ usage(stderr);
do {
res = set_loop(device, file, off, slimit, encryption, pfd, &ro, keysz, hash_pass);
if (res == 2 && find) {
diff --git a/mount/mount.8 b/mount/mount.8
index 4146958a..d8797e4e 100644
--- a/mount/mount.8
+++ b/mount/mount.8
@@ -596,6 +596,15 @@ was known as
Note, the real list of all supported filesystems depends on your
kernel.
+The programs
+.B mount
+and
+.B umount
+support filesystem subtypes. The subtype is defined by '.subtype' suffix. For
+example 'fuse.sshfs'. It's recommended to use subtype notation rather than add
+any prefix to the mount source (for example 'sshfs#example.com' is
+depreacated).
+
For most types all the
.B mount
program has to do is issue a simple
@@ -2646,10 +2655,13 @@ The syntax of external mount helpers is:
.RB [ \-sfnv ]
.RB [ \-o
.IR options ]
+.RB [ \-t
+.IR type.subtype ]
.RE
-where the <suffix> is filesystem type and \-sfnvo options have same meaning like
-standard mount options.
+where the <type> is filesystem type and \-sfnvo options have same meaning like
+standard mount options. The \-t option is used for filesystems with subtypes
+support (for example /sbin/mount.fuse -t fuse.sshfs).
.SH FILES
.TP 18n
diff --git a/mount/mount.c b/mount/mount.c
index a412bc37..0c02bdaa 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -503,9 +503,11 @@ parse_opts (const char *options, int *flags, char **extra_opts) {
if (readwrite)
*flags &= ~MS_RDONLY;
- if (mounttype & MS_PROPAGATION)
- *flags &= ~MS_BIND;
*flags |= mounttype;
+
+ /* The propagation flags should not be used together with any other flags */
+ if (*flags & MS_PROPAGATION)
+ *flags &= MS_PROPAGATION;
}
/* Try to build a canonical options string. */
@@ -674,13 +676,22 @@ check_special_mountprog(const char *spec, const char *node, const char *type, in
path = strtok(search_path, ":");
while (path) {
+ int type_opt = 0;
+
res = snprintf(mountprog, sizeof(mountprog), "%s/mount.%s",
path, type);
path = strtok(NULL, ":");
if (res >= sizeof(mountprog) || res < 0)
continue;
- if (stat(mountprog, &statbuf))
+ res = stat(mountprog, &statbuf);
+ if (res == -1 && errno == ENOENT && strchr(type, '.')) {
+ /* If type ends with ".subtype" try without it */
+ *strrchr(mountprog, '.') = '\0';
+ type_opt = 1;
+ res = stat(mountprog, &statbuf);
+ }
+ if (res)
continue;
if (verbose)
@@ -688,7 +699,7 @@ check_special_mountprog(const char *spec, const char *node, const char *type, in
switch (fork()) {
case 0: { /* child */
- char *oo, *mountargs[10];
+ char *oo, *mountargs[12];
int i = 0;
if (setgid(getgid()) < 0)
@@ -713,7 +724,11 @@ check_special_mountprog(const char *spec, const char *node, const char *type, in
mountargs[i++] = "-o"; /* 8 */
mountargs[i++] = oo; /* 9 */
}
- mountargs[i] = NULL; /* 10 */
+ if (type_opt) {
+ mountargs[i++] = "-t"; /* 10 */
+ mountargs[i++] = (char *) type; /* 11 */
+ }
+ mountargs[i] = NULL; /* 12 */
if (verbose > 2) {
i = 0;
@@ -2156,10 +2171,11 @@ getfs(const char *spec, const char *uuid, const char *label)
/*
* D) remount -- try /etc/mtab
* Earlier mtab was tried first, but this would sometimes try the
- * wrong mount in case mtab had the root device entry wrong.
+ * wrong mount in case mtab had the root device entry wrong. Try
+ * the last occurrence first, since that is the visible mount.
*/
if (!mc && (devname || spec))
- mc = getmntfile (devname ? devname : spec);
+ mc = getmntfilebackward (devname ? devname : spec, NULL);
my_free(devname);
return mc;
diff --git a/mount/sundries.c b/mount/sundries.c
index 1d9eb88e..98f46949 100644
--- a/mount/sundries.c
+++ b/mount/sundries.c
@@ -256,7 +256,9 @@ is_pseudo_fs(const char *type)
streq(type, "cgroup") ||
streq(type, "cpuset") ||
streq(type, "rpc_pipefs") ||
- streq(type, "devpts"))
+ streq(type, "devpts") ||
+ streq(type, "securityfs") ||
+ streq(type, "debugfs"))
return 1;
return 0;
}
diff --git a/mount/umount.8 b/mount/umount.8
index 5ef861aa..fac88785 100644
--- a/mount/umount.8
+++ b/mount/umount.8
@@ -147,9 +147,13 @@ The syntax of external umount helpers is:
.BI /sbin/umount. <suffix>
.RI { dir | device }
.RB [ \-nlfvr ]
+.RB [ \-t
+.IR type.subtype ]
.br
where the <suffix> is filesystem type or a value from "uhelper=" mtab option.
+The \-t option is used for filesystems with subtypes support (for example
+/sbin/mount.fuse -t fuse.sshfs).
The uhelper (unprivileged umount helper) is possible to used when non-root user
wants to umount a mountpoint which is not defined in the /etc/fstab file (e.g
diff --git a/mount/umount.c b/mount/umount.c
index 5bd53604..0ad7c5f9 100644
--- a/mount/umount.c
+++ b/mount/umount.c
@@ -103,11 +103,20 @@ check_special_umountprog(const char *spec, const char *node,
return 0;
if (strlen(type) < 100) {
+ int type_opt = 0;
+
sprintf(umountprog, "/sbin/umount.%s", type);
- if (stat(umountprog, &statbuf) == 0) {
+ res = stat(umountprog, &statbuf);
+ if (res == -1 && errno == ENOENT && strchr(type, '.')) {
+ /* If type ends with ".subtype" try without it */
+ *strrchr(umountprog, '.') = '\0';
+ type_opt = 1;
+ res = stat(umountprog, &statbuf);
+ }
+ if (res == 0) {
res = fork();
if (res == 0) {
- char *umountargs[8];
+ char *umountargs[10];
int i = 0;
if(setgid(getgid()) < 0)
@@ -128,6 +137,10 @@ check_special_umountprog(const char *spec, const char *node,
umountargs[i++] = "-v";
if (remount)
umountargs[i++] = "-r";
+ if (type_opt) {
+ umountargs[i++] = "-t";
+ umountargs[i++] = (char *) type;
+ }
umountargs[i] = NULL;
execv(umountprog, umountargs);
exit(1); /* exec failed */
diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c
index 5597181a..d6abc203 100644
--- a/shlibs/blkid/src/partitions/partitions.c
+++ b/shlibs/blkid/src/partitions/partitions.c
@@ -833,7 +833,7 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr,
for (i = 0; i < nparts; i++) {
blkid_partition par = &ls->parts[i];
- if (par->start + par->size > pr->size) {
+ if (par->start + par->size > (pr->size >> 9)) {
DBG(DEBUG_LOWPROBE, printf("partition #%d overflows "
"device (off=%lu size=%lu)\n",
par->partno, par->start, par->size));
diff --git a/shlibs/blkid/src/superblocks/ext.c b/shlibs/blkid/src/superblocks/ext.c
index b1bc2a8a..6dfe5283 100644
--- a/shlibs/blkid/src/superblocks/ext.c
+++ b/shlibs/blkid/src/superblocks/ext.c
@@ -131,53 +131,6 @@ struct ext2_super_block {
#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP
#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP
-
-#ifdef FUCK
-
-/* for s_flags */
-#define EXT2_FLAGS_TEST_FILESYS 0x0004
-
-/* for s_feature_compat */
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
-
-/* for s_feature_ro_compat */
-#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
-#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
-#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
-#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
-#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
-#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
-#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
-
-/* for s_feature_incompat */
-#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
-#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
-#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
-#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
-
-#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT2_FEATURE_INCOMPAT_META_BG)
-#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
-#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
-
-#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
-#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER| \
- EXT2_FEATURE_INCOMPAT_META_BG)
-#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED (~EXT3_FEATURE_INCOMPAT_SUPP)
-#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT3_FEATURE_RO_COMPAT_SUPP)
-
-#endif
-
/*
* Check to see if a filesystem is in /proc/filesystems.
* Returns 1 if found, 0 if not
diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h
index ddd86ea2..6145b730 100644
--- a/shlibs/mount/src/mountP.h
+++ b/shlibs/mount/src/mountP.h
@@ -70,8 +70,6 @@ extern char *strndup(const char *s, size_t n);
extern char *strnchr(const char *s, size_t maxlen, int c);
#endif
extern char *mnt_get_username(const uid_t uid);
-extern char *mnt_strconcat3(char *s, const char *t, const char *u);
-
/*
* Generic iterator
diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c
index f487383a..6133cdd7 100644
--- a/shlibs/mount/src/utils.c
+++ b/shlibs/mount/src/utils.c
@@ -265,33 +265,6 @@ int mnt_match_options(const char *optstr, const char *pattern)
}
/*
- * Reallocates its first arg @s - typical use: s = mnt_strconcat3(s,t,u);
- * Returns reallocated @s ion succes or NULL in case of error.
- */
-char *mnt_strconcat3(char *s, const char *t, const char *u)
-{
- size_t len = 0;
-
- len = (s ? strlen(s) : 0) + (t ? strlen(t) : 0) + (u ? strlen(u) : 0);
-
- if (!len)
- return NULL;
- if (!s) {
- s = malloc(len + 1);
- *s = '\0';
- } else
- s = realloc(s, len + 1);
-
- if (!s)
- return NULL;
- if (t)
- strcat(s, t);
- if (u)
- strcat(s, u);
- return s;
-}
-
-/*
* Returns allocated string with username or NULL.
*/
char *mnt_get_username(const uid_t uid)
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index fd184aaf..f1a7dcb7 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -111,12 +111,12 @@ main(int argc, char *argv[]) {
if (bufsize) {
sz = bufsize + 8;
- buf = (char *) malloc(sz);
+ buf = (char *) malloc(sz * sizeof(char));
n = klogctl(cmd, buf, sz);
} else {
sz = 16392;
while (1) {
- buf = (char *) malloc(sz);
+ buf = (char *) malloc(sz * sizeof(char));
n = klogctl(3, buf, sz); /* read only */
if (n != sz || sz > (1<<28))
break;
@@ -147,5 +147,6 @@ main(int argc, char *argv[]) {
}
if (lastc != '\n')
putchar('\n');
+ free(buf);
return 0;
}
diff --git a/sys-utils/flock.c b/sys-utils/flock.c
index 1f1c563b..20004cae 100644
--- a/sys-utils/flock.c
+++ b/sys-utils/flock.c
@@ -298,8 +298,8 @@ int main(int argc, char *argv[])
} else if ( f == 0 ) {
if ( do_close )
close(fd);
- err = errno;
execvp(cmd_argv[0], cmd_argv);
+ err = errno;
/* execvp() failed */
fprintf(stderr, "%s: %s: %s\n", program, cmd_argv[0], strerror(err));
_exit((err == ENOMEM) ? EX_OSERR: EX_UNAVAILABLE);
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index 4f78ee6b..30e08a57 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -22,6 +22,10 @@ Print a help message.
.TP
.BR \-p , " \-\-parse"
Print out in parsable instead of printable format.
+.TP
+.BR \-x , " \-\-hex"
+Use hexadecimal masks for CPU(s) sets (e.g. 0x3). The default is print the sets
+in the list format (e.g. 0,1).
.SH BUGS
The basic overview about CPU family, model, etc. is always based on the first
CPU only.
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 74f5e781..027a2982 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -30,6 +30,7 @@
#include <sys/utsname.h>
#include <unistd.h>
#include <stdarg.h>
+#include <bitops.h>
#include "cpuset.h"
#include "nls.h"
@@ -97,10 +98,12 @@ struct lscpu_desc {
int virtype; /* VIRT_PARA|FULL|NONE ? */
char *mhz;
char *stepping;
+ char *bogomips;
char *flags;
int mode; /* rm, lm or/and tm */
int ncpus; /* number of CPUs */
+ cpu_set_t *online; /* mask with online CPUs */
int nnodes; /* number of NUMA modes */
cpu_set_t **nodemaps; /* array with NUMA nodes */
@@ -125,6 +128,10 @@ static size_t sysrootlen;
static char pathbuf[PATH_MAX];
static int maxcpus; /* size in bits of kernel cpu mask */
+#define is_cpu_online(_d, _cpu) \
+ ((_d) && (_d)->online ? \
+ CPU_ISSET_S((_cpu), CPU_ALLOC_SIZE(maxcpus), (_d)->online) : 0)
+
static FILE *path_fopen(const char *mode, int exit_on_err, const char *path, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
static void path_getstr(char *result, size_t len, const char *path, ...)
@@ -235,17 +242,14 @@ xstrdup(const char *str)
}
static cpu_set_t *
-path_cpuset(const char *path, ...)
+path_cpuparse(int islist, const char *path, va_list ap)
{
FILE *fd;
- va_list ap;
cpu_set_t *set;
size_t setsize, len = maxcpus * 7;
char buf[len];
- va_start(ap, path);
fd = path_vfopen("r", 1, path, ap);
- va_end(ap);
if (!fgets(buf, len, fd))
err(EXIT_FAILURE, _("failed to read: %s"), pathbuf);
@@ -259,8 +263,38 @@ path_cpuset(const char *path, ...)
if (!set)
err(EXIT_FAILURE, _("failed to callocate cpu set"));
- if (cpumask_parse(buf, set, setsize))
- errx(EXIT_FAILURE, _("failed to parse CPU mask %s"), buf);
+ if (islist) {
+ if (cpulist_parse(buf, set, setsize))
+ errx(EXIT_FAILURE, _("failed to parse CPU list %s"), buf);
+ } else {
+ if (cpumask_parse(buf, set, setsize))
+ errx(EXIT_FAILURE, _("failed to parse CPU mask %s"), buf);
+ }
+ return set;
+}
+
+static cpu_set_t *
+path_cpuset(const char *path, ...)
+{
+ va_list ap;
+ cpu_set_t *set;
+
+ va_start(ap, path);
+ set = path_cpuparse(0, path, ap);
+ va_end(ap);
+
+ return set;
+}
+
+static cpu_set_t *
+path_cpulist(const char *path, ...)
+{
+ va_list ap;
+ cpu_set_t *set;
+
+ va_start(ap, path);
+ set = path_cpuparse(1, path, ap);
+ va_end(ap);
return set;
}
@@ -334,6 +368,7 @@ read_basicinfo(struct lscpu_desc *desc)
else if (lookup(buf, "stepping", &desc->stepping)) ;
else if (lookup(buf, "cpu MHz", &desc->mhz)) ;
else if (lookup(buf, "flags", &desc->flags)) ;
+ else if (lookup(buf, "bogomips", &desc->bogomips)) ;
else
continue;
}
@@ -365,6 +400,10 @@ read_basicinfo(struct lscpu_desc *desc)
/* we are reading some /sys snapshot instead of the real /sys,
* let's use any crazy number... */
maxcpus = desc->ncpus > 2048 ? desc->ncpus : 2048;
+
+ /* get mask for online CPUs */
+ if (path_exist(_PATH_SYS_SYSTEM "/cpu/online"))
+ desc->online = path_cpulist(_PATH_SYS_SYSTEM "/cpu/online");
}
static int
@@ -523,7 +562,8 @@ read_topology(struct lscpu_desc *desc, int num)
"/cpu%d/topology/thread_siblings", num);
core_siblings = path_cpuset(_PATH_SYS_CPU
"/cpu%d/topology/core_siblings", num);
- if (num == 0) {
+
+ if (!desc->coremaps) {
int ncores, nsockets, nthreads;
size_t setsize = CPU_ALLOC_SIZE(maxcpus);
@@ -563,7 +603,7 @@ read_cache(struct lscpu_desc *desc, int num)
char buf[256];
int i;
- if (num == 0) {
+ if (!desc->ncaches) {
while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d/cache/index%d",
num, desc->ncaches))
desc->ncaches++;
@@ -670,6 +710,9 @@ print_parsable(struct lscpu_desc *desc)
for (i = 0; i < desc->ncpus; i++) {
+ if (desc->online && !is_cpu_online(desc, i))
+ continue;
+
/* #CPU */
printf("%d", i);
@@ -730,10 +773,28 @@ print_parsable(struct lscpu_desc *desc)
#define print_n(_key, _val) printf("%-23s%d\n", _key, _val)
static void
-print_readable(struct lscpu_desc *desc)
+print_cpuset(const char *key, cpu_set_t *set, int hex)
+{
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
+ size_t setbuflen = 7 * maxcpus;
+ char setbuf[setbuflen], *p;
+
+ if (hex) {
+ p = cpumask_create(setbuf, setbuflen, set, setsize);
+ printf("%-23s0x%s\n", key, p);
+ } else {
+ p = cpulist_create(setbuf, setbuflen, set, setsize);
+ print_s(key, p);
+ }
+
+}
+
+static void
+print_readable(struct lscpu_desc *desc, int hex)
{
char buf[512];
int i;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
print_s(_("Architecture:"), desc->arch);
@@ -755,9 +816,41 @@ print_readable(struct lscpu_desc *desc)
*(p - 2) = '\0';
print_s(_("CPU op-mode(s):"), buf);
}
-
+#ifdef __BYTE_ORDER
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ print_s(_("Byte Order:"), "Little Endian");
+#else
+ print_s(_("Byte Order:"), "Big Endian");
+#endif
+#endif
print_n(_("CPU(s):"), desc->ncpus);
+ if (desc->online)
+ print_cpuset(hex ? _("On-line CPU(s) mask:") :
+ _("On-line CPU(s) list:"),
+ desc->online, hex);
+
+ if (desc->online && CPU_COUNT_S(setsize, desc->online) != desc->ncpus) {
+ cpu_set_t *set;
+
+ /* Linux kernel provides cpuset of off-line CPUs that contains
+ * all configured CPUs (see /sys/devices/system/cpu/offline),
+ * but want to print real (present in system) off-line CPUs only.
+ */
+ set = cpuset_alloc(maxcpus, NULL, NULL);
+ if (!set)
+ err(EXIT_FAILURE, _("failed to callocate cpu set"));
+ CPU_ZERO_S(setsize, set);
+ for (i = 0; i < desc->ncpus; i++) {
+ if (!is_cpu_online(desc, i))
+ CPU_SET_S(i, setsize, set);
+ }
+ print_cpuset(hex ? _("Off-line CPU(s) mask:") :
+ _("Off-line CPU(s) list:"),
+ set, hex);
+ cpuset_free(set);
+ }
+
if (desc->nsockets) {
print_n(_("Thread(s) per core:"), desc->nthreads / desc->ncores);
print_n(_("Core(s) per socket:"), desc->ncores / desc->nsockets);
@@ -776,6 +869,8 @@ print_readable(struct lscpu_desc *desc)
print_s(_("Stepping:"), desc->stepping);
if (desc->mhz)
print_s(_("CPU MHz:"), desc->mhz);
+ if (desc->bogomips)
+ print_s(_("BogoMIPS:"), desc->bogomips);
if (desc->virtflag) {
if (!strcmp(desc->virtflag, "svm"))
print_s(_("Virtualization:"), "AMD-V");
@@ -797,17 +892,9 @@ print_readable(struct lscpu_desc *desc)
}
}
- if (desc->nnodes) {
- size_t setbuflen = 7 * maxcpus;
- char setbuf[setbuflen];
-
- for (i = 0; i < desc->nnodes; i++) {
- snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), i);
- print_s(buf, cpulist_create(
- setbuf, setbuflen,
- desc->nodemaps[i],
- CPU_ALLOC_SIZE(maxcpus)));
- }
+ for (i = 0; i < desc->nnodes; i++) {
+ snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), i);
+ print_cpuset(buf, desc->nodemaps[i], hex);
}
}
@@ -819,19 +906,22 @@ void usage(int rc)
puts(_( "CPU architecture information helper\n\n"
" -h, --help usage information\n"
" -p, --parse print out in parsable instead of printable format.\n"
- " -s, --sysroot use the directory as a new system root.\n"));
+ " -s, --sysroot use the directory as a new system root.\n"
+ " -x, --hex print haxadecimal masks rather than lists of CPU(s)\n"));
+
exit(rc);
}
int main(int argc, char *argv[])
{
struct lscpu_desc _desc, *desc = &_desc;
- int parsable = 0, c, i;
+ int parsable = 0, c, i, hex = 0;
struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
{ "parse", no_argument, 0, 'p' },
{ "sysroot", required_argument, 0, 's' },
+ { "hex", no_argument, 0, 'x' },
{ NULL, 0, 0, 0 }
};
@@ -839,7 +929,7 @@ int main(int argc, char *argv[])
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- while((c = getopt_long(argc, argv, "hps:", longopts, NULL)) != -1) {
+ while((c = getopt_long(argc, argv, "hps:x", longopts, NULL)) != -1) {
switch (c) {
case 'h':
usage(EXIT_SUCCESS);
@@ -851,6 +941,9 @@ int main(int argc, char *argv[])
strncpy(pathbuf, optarg, sizeof(pathbuf));
pathbuf[sizeof(pathbuf) - 1] = '\0';
break;
+ case 'x':
+ hex = 1;
+ break;
default:
usage(EXIT_FAILURE);
}
@@ -861,6 +954,8 @@ int main(int argc, char *argv[])
read_basicinfo(desc);
for (i = 0; i < desc->ncpus; i++) {
+ if (desc->online && !is_cpu_online(desc, i))
+ continue;
read_topology(desc, i);
read_cache(desc, i);
}
@@ -875,7 +970,7 @@ int main(int argc, char *argv[])
if (parsable)
print_parsable(desc);
else
- print_readable(desc);
+ print_readable(desc, hex);
return EXIT_SUCCESS;
}
diff --git a/tests/expected/blkid/md-raid0-whole b/tests/expected/blkid/md-raid0-whole
new file mode 100644
index 00000000..2e0b824a
--- /dev/null
+++ b/tests/expected/blkid/md-raid0-whole
@@ -0,0 +1,51 @@
+Initialize devices
+Create RAID device
+Create partitions on RAID device
+Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
+
+Changes will remain in memory only, until you decide to write them.
+After that, of course, the previous content won't be recoverable.
+
+Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 1): First sector (2048-204543, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-204543, default 204543):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 2): First sector (22528-204543, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-204543, default 204543): Using default value 204543
+
+Command (m for help):
+Disk /dev/md8: 104 MB, 104726528 bytes
+2 heads, 4 sectors/track, 25568 cylinders, total 204544 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 65536 bytes / 131072 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/md8p1 2048 22527 10240 83 Linux
+/dev/md8p2 22528 204543 91008 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Probe first RAID member
+ID_FS_TYPE=linux_raid_member
+ID_FS_USAGE=raid
+
+
+ID_FS_VERSION=0.90.0
+Probe second RAID member
+ID_FS_TYPE=linux_raid_member
+ID_FS_USAGE=raid
+
+
+ID_FS_VERSION=0.90.0
+Stop RAID device
+Deinitialize devices
diff --git a/tests/expected/fdisk/id b/tests/expected/fdisk/id
new file mode 100644
index 00000000..4801f816
--- /dev/null
+++ b/tests/expected/fdisk/id
@@ -0,0 +1,5 @@
+Initialize empty image
+Create MBR with ID=0x1
+Disk identifier: 0x00000001
+Create MBR with ID=0x2
+Disk identifier: 0x00000002
diff --git a/tests/expected/lscpu/lscpu-i386-amdshanghai b/tests/expected/lscpu/lscpu-i386-amdshanghai
index 4e300885..5f2d74ec 100644
--- a/tests/expected/lscpu/lscpu-i386-amdshanghai
+++ b/tests/expected/lscpu/lscpu-i386-amdshanghai
@@ -8,6 +8,7 @@ CPU family: 16
Model: 4
Stepping: 0
CPU MHz: 1995.158
+BogoMIPS: 3989.99
Virtualization: AMD-V
L1d cache: 512K
L1i cache: 512K
diff --git a/tests/expected/lscpu/lscpu-i386-dellpe700 b/tests/expected/lscpu/lscpu-i386-dellpe700
index 5b7562b6..d1d95c79 100644
--- a/tests/expected/lscpu/lscpu-i386-dellpe700
+++ b/tests/expected/lscpu/lscpu-i386-dellpe700
@@ -8,6 +8,7 @@ CPU family: 15
Model: 2
Stepping: 9
CPU MHz: 3391.773
+BogoMIPS: 6781.99
# The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-i386-intels5000phb b/tests/expected/lscpu/lscpu-i386-intels5000phb
index 0436aae5..24ca496a 100644
--- a/tests/expected/lscpu/lscpu-i386-intels5000phb
+++ b/tests/expected/lscpu/lscpu-i386-intels5000phb
@@ -8,6 +8,7 @@ CPU family: 6
Model: 15
Stepping: 7
CPU MHz: 1596.044
+BogoMIPS: 3191.91
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
diff --git a/tests/expected/lscpu/lscpu-x86_64-dellr710 b/tests/expected/lscpu/lscpu-x86_64-dellr710
index 43679dc4..d436f22f 100644
--- a/tests/expected/lscpu/lscpu-x86_64-dellr710
+++ b/tests/expected/lscpu/lscpu-x86_64-dellr710
@@ -9,6 +9,7 @@ CPU family: 6
Model: 26
Stepping: 5
CPU MHz: 2527.073
+BogoMIPS: 5053.32
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
diff --git a/tests/expected/lscpu/lscpu-x86_64-hpdl585 b/tests/expected/lscpu/lscpu-x86_64-hpdl585
index 54a1a242..2dc36c06 100644
--- a/tests/expected/lscpu/lscpu-x86_64-hpdl585
+++ b/tests/expected/lscpu/lscpu-x86_64-hpdl585
@@ -9,6 +9,7 @@ CPU family: 16
Model: 2
Stepping: 3
CPU MHz: 2210.188
+BogoMIPS: 4420.50
Virtualization: AMD-V
L1d cache: 512K
L1i cache: 512K
diff --git a/tests/expected/lscpu/lscpu-x86_64-ibme326m b/tests/expected/lscpu/lscpu-x86_64-ibme326m
index ccc64a07..98aea983 100644
--- a/tests/expected/lscpu/lscpu-x86_64-ibme326m
+++ b/tests/expected/lscpu/lscpu-x86_64-ibme326m
@@ -9,6 +9,7 @@ CPU family: 15
Model: 33
Stepping: 2
CPU MHz: 1995.058
+BogoMIPS: 3989.41
L1d cache: 1024K
L1i cache: 1024K
L2 cache: 1024K
diff --git a/tests/expected/lscpu/lscpu-x86_64-necem14 b/tests/expected/lscpu/lscpu-x86_64-necem14
index c823f7e7..d3c4f1ba 100644
--- a/tests/expected/lscpu/lscpu-x86_64-necem14
+++ b/tests/expected/lscpu/lscpu-x86_64-necem14
@@ -9,6 +9,7 @@ CPU family: 15
Model: 4
Stepping: 3
CPU MHz: 3790.599
+BogoMIPS: 7579.94
L1d cache: 16K
L2 cache: 2048K
NUMA node0 CPU(s): 0,1
diff --git a/tests/ts/blkid/md-raid0-whole b/tests/ts/blkid/md-raid0-whole
new file mode 100755
index 00000000..3acc4a9c
--- /dev/null
+++ b/tests/ts/blkid/md-raid0-whole
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+#
+# This file is part of util-linux-ng.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="MD raid0 (whole-disks)"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+[ -x /sbin/mdadm ] || ts_skip "missing mdadm"
+
+set -o pipefail
+
+ts_log "Initialize devices"
+IMGNAME="${TS_OUTDIR}/${TS_TESTNAME}"
+
+DEVICE1=$(ts_device_init 50 ${IMGNAME}1.img)
+[ "$?" == 0 ] || ts_die "Cannot init device1"
+
+DEVICE2=$(ts_device_init 50 ${IMGNAME}2.img)
+[ "$?" == 0 ] || ts_die "Cannot init device2" $DEVICE1
+
+MD_DEVNAME=md8
+MD_DEVICE=/dev/${MD_DEVNAME}
+
+/sbin/mdadm -q -S ${MD_DEVICE} &> /dev/null
+
+ts_log "Create RAID device"
+/sbin/mdadm -q --create ${MD_DEVICE} --metadata=0.90 --chunk=64 --level=0 \
+ --raid-devices=2 ${DEVICE1} ${DEVICE2} >> $TS_OUTPUT 2>&1
+
+ts_log "Create partitions on RAID device"
+$TS_CMD_FDISK ${MD_DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+n
+p
+1
+
++10M
+n
+p
+2
+
+
+p
+w
+q
+EOF
+
+sleep 3
+
+ts_log "Probe first RAID member"
+$TS_CMD_BLKID -p -o udev $DEVICE1 2>&1 | sort >> $TS_OUTPUT
+
+ts_log "Probe second RAID member"
+$TS_CMD_BLKID -p -o udev $DEVICE1 2>&1 | sort >> $TS_OUTPUT
+
+ts_log "Stop RAID device"
+/sbin/mdadm -q -S ${MD_DEVICE} >> $TS_OUTPUT 2>&1
+
+sleep 3
+
+ts_log "Deinitialize devices"
+ts_device_deinit $DEVICE1
+ts_device_deinit $DEVICE2
+
+# remove disk ID and generated UUIDs
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+sed -i -e 's/ID_FS_UUID.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/id b/tests/ts/fdisk/id
new file mode 100755
index 00000000..99840a25
--- /dev/null
+++ b/tests/ts/fdisk/id
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+#
+# This file is part of util-linux-ng.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="doslabel tests"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+FDISK_CMD_ID1="x\ni\n0x1\nr\nw\n"
+FDISK_CMD_ID2="x\ni\n0x2\nr\nw\n"
+
+ts_log "Initialize empty image"
+TEST_IMAGE_NAME=$(ts_image_init 10)
+
+ts_log "Create MBR with ID=0x1"
+echo -e "${FDISK_CMD_ID1}" | $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
+$TS_CMD_FDISK -l ${TEST_IMAGE_NAME} | grep identifier >> $TS_OUTPUT
+
+ts_log "Create MBR with ID=0x2"
+echo -e "${FDISK_CMD_ID2}" | $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
+$TS_CMD_FDISK -l ${TEST_IMAGE_NAME} | grep identifier >> $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/lscpu/lscpu b/tests/ts/lscpu/lscpu
index 2c7f2a45..a3c6e492 100755
--- a/tests/ts/lscpu/lscpu
+++ b/tests/ts/lscpu/lscpu
@@ -40,6 +40,9 @@ for dump in $(ls $TS_SELF/dumps/*.tar.gz | sort); do
"${TS_CMD_LSCPU}" -p -s "${dumpdir}/${name}" \
>>"${TS_OUTPUT}" 2>&1
+ # LE/BE depends on binary
+ sed -i -e '/Byte Order:.*/d' $TS_OUTPUT
+
ts_finalize_subtest
done
diff --git a/text-utils/rev.c b/text-utils/rev.c
index 3ae38cfd..907b032b 100644
--- a/text-utils/rev.c
+++ b/text-utils/rev.c
@@ -36,12 +36,16 @@
* Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle
* last line that has no newline correctly.
* 3-Jun-1998: Patched by Nicolai Langfeldt to work better on Linux:
- * Handle any-length-lines. Code copied from util-linux' setpwnam.c
+ * Handle any-length-lines. Code copied from util-linux' setpwnam.c
* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
- * added Native Language Support
+ * added Native Language Support
* 1999-09-19 Bruno Haible <haible@clisp.cons.org>
- * modified to work correctly in multi-byte locales
- *
+ * modified to work correctly in multi-byte locales
+ * July 2010 - Davidlohr Bueso <dave@gnu.org>
+ * Fixed memory leaks (including Linux signal handling)
+ * Added some memory allocation error handling
+ * Lowered the default buffer size to 256, instead of 512 bytes
+ * Changed tab indentation to 8 chars for better reading the code
*/
#include <stdarg.h>
@@ -52,94 +56,115 @@
#include <string.h>
#include <unistd.h>
#include <err.h>
+#include <signal.h>
#include "nls.h"
#include "widechar.h"
-void usage(void);
+wchar_t *buf;
-int
-main(int argc, char *argv[])
+static void sig_handler(int signo)
{
- register char *filename;
- register wchar_t *t;
- size_t buflen = 512;
- wchar_t *p = malloc(buflen*sizeof(wchar_t));
- size_t len;
- FILE *fp;
- int ch, rval;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- while ((ch = getopt(argc, argv, "")) != -1)
- switch(ch) {
- case '?':
- default:
- usage();
- }
-
- argc -= optind;
- argv += optind;
-
- fp = stdin;
- filename = "stdin";
- rval = 0;
- do {
- if (*argv) {
- if ((fp = fopen(*argv, "r")) == NULL) {
- warn("cannot open %s", *argv );
- rval = 1;
- ++argv;
- continue;
- }
- filename = *argv++;
- }
-
- while (fgetws(p, buflen, fp)) {
-
- len = wcslen(p);
-
- /* This is my hack from setpwnam.c -janl */
- while (p[len-1] != '\n' && !feof(fp)) {
- /* Extend input buffer if it failed getting the whole line */
-
- /* So now we double the buffer size */
- buflen *= 2;
-
- p = realloc(p, buflen*sizeof(wchar_t));
- if (p == NULL)
- err(1, _("unable to allocate bufferspace"));
-
- /* And fill the rest of the buffer */
- if (fgetws(&p[len], buflen/2, fp) == NULL) break;
-
- len = wcslen(p);
-
- /* That was a lot of work for nothing. Gimme perl! */
- }
-
- t = p + len - 1 - (*(p+len-1)=='\r' || *(p+len-1)=='\n');
- for ( ; t >= p; --t)
- if (*t != 0)
- putwchar(*t);
- putwchar('\n');
- }
- fflush(fp);
- if (ferror(fp)) {
- warn("%s", filename);
- rval = 1;
- }
- if (fclose(fp))
- rval = 1;
- } while(*argv);
- exit(rval);
+ free(buf);
+ exit(EXIT_SUCCESS);
}
-void
-usage(void)
+static void __attribute__((__noreturn__)) usage(FILE *out)
{
- (void)fprintf(stderr, _("usage: rev [file ...]\n"));
- exit(1);
+ fprintf(out, _("Usage: %s [file ...]\n"),
+ program_invocation_short_name);
+
+ fprintf(out, _("\nFor more information see rev(1).\n"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
+
+int main(int argc, char *argv[])
+{
+ char *filename = "stdin";
+ wchar_t *t;
+ size_t len, bufsiz = BUFSIZ;
+ FILE *fp = stdin;
+ int ch, rval = EXIT_SUCCESS;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ signal(SIGINT, sig_handler);
+ signal(SIGTERM, sig_handler);
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ case 'h':
+ usage(stdout);
+ default:
+ usage(stderr);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ do {
+ if (*argv) {
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ warn(_("%s: open failed"), *argv );
+ rval = EXIT_FAILURE;
+ ++argv;
+ continue;
+ }
+ filename = *argv++;
+ }
+
+ buf = malloc(bufsiz * sizeof(wchar_t));
+ if (!buf)
+ err(EXIT_FAILURE, _("malloc failed"));
+
+ while (fgetws(buf, bufsiz, fp)) {
+ len = wcslen(buf);
+
+ /* This is my hack from setpwnam.c -janl */
+ while (buf[len-1] != '\n' && !feof(fp)) {
+ wchar_t *x;
+
+ /* Extend input buffer if it failed getting the whole line */
+
+ /* So now we double the buffer size */
+ bufsiz *= 2;
+
+ x = realloc(buf, bufsiz * sizeof(wchar_t));
+ if (!x) {
+ free(buf);
+ err(EXIT_FAILURE, _("realloc failed"));
+ }
+ buf = x;
+
+ /* And fill the rest of the buffer */
+ if (!fgetws(&buf[len], bufsiz/2, fp))
+ break;
+
+ len = wcslen(buf);
+ }
+
+ t = buf + len - 1 - (*(buf+len-1)=='\r' || *(buf+len-1)=='\n');
+ for ( ; t >= buf; --t) {
+ if (*t != 0)
+ putwchar(*t);
+ }
+ putwchar('\n');
+ }
+
+ fflush(fp);
+ if (ferror(fp)) {
+ warn("%s", filename);
+ rval = EXIT_FAILURE;
+ }
+ if (fclose(fp))
+ rval = EXIT_FAILURE;
+ } while(*argv);
+
+ free(buf);
+ return rval;
+}
+
diff --git a/text-utils/tailf.c b/text-utils/tailf.c
index 75998ce7..dc18b2a6 100644
--- a/text-utils/tailf.c
+++ b/text-utils/tailf.c
@@ -88,6 +88,7 @@ roll_file(const char *filename, off_t *size)
char buf[BUFSIZ];
int fd;
struct stat st;
+ off_t pos;
if (!(fd = open(filename, O_RDONLY)))
err(EXIT_FAILURE, _("cannot open \"%s\" for read"), filename);
@@ -111,8 +112,16 @@ roll_file(const char *filename, off_t *size)
}
fflush(stdout);
}
+
+ pos = lseek(fd, 0, SEEK_CUR);
+
+ /* If we've successfully read something, use the file position, this
+ * avoids data duplication. If we read nothing or hit an error, reset
+ * to the reported size, this handles truncated files.
+ */
+ *size = (pos != -1 && pos != *size) ? pos : st.st_size;
+
close(fd);
- *size = st.st_size;
}
static void