summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS2
-rw-r--r--TODO19
-rw-r--r--configure.ac73
-rw-r--r--disk-utils/.gitignore1
-rw-r--r--disk-utils/Makefile.am36
-rw-r--r--disk-utils/blockdev.c8
-rw-r--r--disk-utils/mkswap.c45
-rw-r--r--disk-utils/swaplabel.866
-rw-r--r--disk-utils/swaplabel.c226
-rw-r--r--fdisk/Makefile.am4
-rw-r--r--fdisk/cfdisk.c61
-rw-r--r--fdisk/fdisk.814
-rw-r--r--fdisk/fdisk.c373
-rw-r--r--fdisk/fdisk.h2
-rw-r--r--fdisk/fdiskbsdlabel.c4
-rw-r--r--fdisk/fdisksunlabel.c24
-rw-r--r--fdisk/sfdisk.c5
-rw-r--r--fsck/fsck.c1
-rw-r--r--hwclock/hwclock.87
-rw-r--r--hwclock/hwclock.c41
-rw-r--r--include/Makefile.am6
-rw-r--r--include/blkdev.h9
-rw-r--r--include/c.h16
-rw-r--r--include/fsprobe.h1
-rw-r--r--include/mangle.h14
-rw-r--r--include/mbsalign.h45
-rw-r--r--include/pathnames.h4
-rw-r--r--include/strtosize.h8
-rw-r--r--include/swapheader.h8
-rw-r--r--include/writeall.h25
-rw-r--r--lib/Makefile.am5
-rw-r--r--lib/blkdev.c117
-rw-r--r--lib/canonicalize.c1
-rw-r--r--lib/fsprobe.c63
-rw-r--r--lib/mangle.c116
-rw-r--r--lib/mbsalign.c288
-rw-r--r--lib/strtosize.c148
-rw-r--r--misc-utils/Makefile.am11
-rw-r--r--misc-utils/blkid.878
-rw-r--r--misc-utils/blkid.c328
-rw-r--r--misc-utils/cal.c92
-rw-r--r--misc-utils/logger.18
-rw-r--r--misc-utils/script.14
-rw-r--r--misc-utils/script.c68
-rw-r--r--misc-utils/wipefs.86
-rw-r--r--misc-utils/wipefs.c28
-rw-r--r--mount/Makefile.am9
-rw-r--r--mount/fstab.c2
-rw-r--r--mount/fstab.h1
-rw-r--r--mount/lomount.c16
-rw-r--r--mount/losetup.810
-rw-r--r--mount/mount.866
-rw-r--r--mount/mount.c82
-rw-r--r--mount/mount_mntent.c55
-rw-r--r--mount/swapon.c18
-rw-r--r--mount/umount.86
-rw-r--r--mount/umount.c15
-rw-r--r--partx/addpart.c4
-rw-r--r--partx/partx.c5
-rw-r--r--schedutils/ionice.c4
-rw-r--r--shlibs/blkid/samples/partitions.c35
-rw-r--r--shlibs/blkid/src/blkid.h.in12
-rw-r--r--shlibs/blkid/src/blkid.sym7
-rw-r--r--shlibs/blkid/src/blkidP.h22
-rw-r--r--shlibs/blkid/src/dev.c2
-rw-r--r--shlibs/blkid/src/devname.c1
-rw-r--r--shlibs/blkid/src/devno.c66
-rw-r--r--shlibs/blkid/src/getsize.c198
-rw-r--r--shlibs/blkid/src/partitions/Makefile.am1
-rw-r--r--shlibs/blkid/src/partitions/bsd.c6
-rw-r--r--shlibs/blkid/src/partitions/dos.c52
-rw-r--r--shlibs/blkid/src/partitions/gpt.c12
-rw-r--r--shlibs/blkid/src/partitions/mac.c2
-rw-r--r--shlibs/blkid/src/partitions/minix.c8
-rw-r--r--shlibs/blkid/src/partitions/partitions.c325
-rw-r--r--shlibs/blkid/src/partitions/partitions.h9
-rw-r--r--shlibs/blkid/src/partitions/sgi.c11
-rw-r--r--shlibs/blkid/src/partitions/solaris_x86.c8
-rw-r--r--shlibs/blkid/src/partitions/sun.c55
-rw-r--r--shlibs/blkid/src/partitions/ultrix.c88
-rw-r--r--shlibs/blkid/src/partitions/unixware.c7
-rw-r--r--shlibs/blkid/src/probe.c221
-rw-r--r--shlibs/blkid/src/read.c14
-rw-r--r--shlibs/blkid/src/save.c8
-rw-r--r--shlibs/blkid/src/superblocks/adaptec_raid.c4
-rw-r--r--shlibs/blkid/src/superblocks/befs.c14
-rw-r--r--shlibs/blkid/src/superblocks/ddf_raid.c7
-rw-r--r--shlibs/blkid/src/superblocks/drbd.c15
-rw-r--r--shlibs/blkid/src/superblocks/highpoint_raid.c3
-rw-r--r--shlibs/blkid/src/superblocks/isw_raid.c4
-rw-r--r--shlibs/blkid/src/superblocks/jmicron_raid.c4
-rw-r--r--shlibs/blkid/src/superblocks/linux_raid.c8
-rw-r--r--shlibs/blkid/src/superblocks/lsi_raid.c4
-rw-r--r--shlibs/blkid/src/superblocks/luks.c2
-rw-r--r--shlibs/blkid/src/superblocks/minix.c10
-rw-r--r--shlibs/blkid/src/superblocks/nvidia_raid.c5
-rw-r--r--shlibs/blkid/src/superblocks/promise_raid.c7
-rw-r--r--shlibs/blkid/src/superblocks/silicon_raid.c7
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.c150
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.h2
-rw-r--r--shlibs/blkid/src/superblocks/swap.c20
-rw-r--r--shlibs/blkid/src/superblocks/sysv.c14
-rw-r--r--shlibs/blkid/src/superblocks/ufs.c8
-rw-r--r--shlibs/blkid/src/superblocks/via_raid.c4
-rw-r--r--shlibs/blkid/src/superblocks/zfs.c203
-rw-r--r--shlibs/blkid/src/topology/dm.c2
-rw-r--r--shlibs/blkid/src/topology/evms.c4
-rw-r--r--shlibs/blkid/src/topology/ioctl.c20
-rw-r--r--shlibs/blkid/src/topology/lvm.c2
-rw-r--r--shlibs/blkid/src/topology/md.c4
-rw-r--r--shlibs/blkid/src/topology/sysfs.c111
-rw-r--r--shlibs/blkid/src/topology/topology.c40
-rw-r--r--shlibs/blkid/src/topology/topology.h2
-rw-r--r--shlibs/blkid/src/verify.c38
-rw-r--r--shlibs/uuid/src/gen_uuid.c2
-rw-r--r--sys-utils/Makefile.am1
-rw-r--r--sys-utils/fallocate.19
-rw-r--r--sys-utils/fallocate.c40
-rw-r--r--sys-utils/ldattach.811
-rw-r--r--sys-utils/ldattach.c106
-rw-r--r--sys-utils/lscpu.c2
-rw-r--r--sys-utils/rtcwake.811
-rw-r--r--sys-utils/rtcwake.c79
-rw-r--r--sys-utils/unshare.13
-rw-r--r--sys-utils/unshare.c7
-rw-r--r--tests/README11
-rw-r--r--tests/commands.sh.in1
-rw-r--r--tests/expected/blkid/low-probe-cramfs2
-rw-r--r--tests/expected/blkid/low-probe-ext22
-rw-r--r--tests/expected/blkid/low-probe-ext32
-rw-r--r--tests/expected/blkid/low-probe-fat2
-rw-r--r--tests/expected/blkid/low-probe-gfs22
-rw-r--r--tests/expected/blkid/low-probe-hpfs2
-rw-r--r--tests/expected/blkid/low-probe-iso2
-rw-r--r--tests/expected/blkid/low-probe-iso-joliet2
-rw-r--r--tests/expected/blkid/low-probe-iso-rr-joliet2
-rw-r--r--tests/expected/blkid/low-probe-jfs2
-rw-r--r--tests/expected/blkid/low-probe-lvm22
-rw-r--r--tests/expected/blkid/low-probe-ntfs2
-rw-r--r--tests/expected/blkid/low-probe-ocfs22
-rw-r--r--tests/expected/blkid/low-probe-reiser32
-rw-r--r--tests/expected/blkid/low-probe-reiser42
-rw-r--r--tests/expected/blkid/low-probe-romfs2
-rw-r--r--tests/expected/blkid/low-probe-small-fat322
-rw-r--r--tests/expected/blkid/low-probe-swap12
-rw-r--r--tests/expected/blkid/low-probe-tuxonice5
-rw-r--r--tests/expected/blkid/low-probe-udf2
-rw-r--r--tests/expected/blkid/low-probe-vmfs2
-rw-r--r--tests/expected/blkid/low-probe-xfs2
-rw-r--r--tests/expected/blkid/low-probe-zfs12
-rw-r--r--tests/expected/blkid/md-raid1-part66
-rw-r--r--tests/expected/blkid/md-raid1-whole58
-rw-r--r--tests/expected/fdisk/align-512-4K78
-rw-r--r--tests/expected/fdisk/align-512-4K-6379
-rw-r--r--tests/expected/fdisk/align-512-4K-md99
-rw-r--r--tests/expected/fdisk/align-512-4K-topology78
-rw-r--r--tests/expected/fdisk/align-512-51263
-rw-r--r--tests/expected/fdisk/align-512-512-topology74
-rw-r--r--tests/expected/fdisk/oddinput5
-rw-r--r--tests/expected/misc/strtosize30
-rw-r--r--tests/functions.sh11
-rw-r--r--tests/ts/blkid/images-fs/tuxonice.img.bz2bin0 -> 2765314 bytes
-rwxr-xr-xtests/ts/blkid/md-raid1-part92
-rwxr-xr-xtests/ts/blkid/md-raid1-whole88
-rwxr-xr-xtests/ts/fdisk/align-512-4K91
-rwxr-xr-xtests/ts/fdisk/align-512-4K-6391
-rwxr-xr-xtests/ts/fdisk/align-512-4K-md105
-rwxr-xr-xtests/ts/fdisk/align-512-51274
-rwxr-xr-xtests/ts/fdisk/align-512-512-topology91
-rwxr-xr-xtests/ts/fdisk/doslabel24
-rwxr-xr-xtests/ts/fdisk/oddinput2
-rwxr-xr-xtests/ts/fdisk/sunlabel16
-rwxr-xr-xtests/ts/misc/strtosize60
173 files changed, 5126 insertions, 1281 deletions
diff --git a/AUTHORS b/AUTHORS
index 803a76d0..b4fbee6c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,8 @@ AUTHORS (merged projects & commands):
Jeremy Katz <katzj@redhat.com>
unshare: Mikhail Gusarov <dottedmag@dottedmag.net>
wipefs: Karel Zak <kzak@redhat.com>
+ swaplabel: Jason Borden <jborden@bluehost.com>
+ Karel Zak <kzak@redhat.com>
CONTRIBUTORS:
diff --git a/TODO b/TODO
index bdf19e6c..f73c78a3 100644
--- a/TODO
+++ b/TODO
@@ -1,15 +1,9 @@
libblkid
--------
- - add command line interface for blkid_probe_filter_types():
-
- # blkid -p -o udev --filter-type nofat
-
- add -<BE|LE> suffix to test images for native-endian filesystems (e.g. swap)
and add support for such functionality to tests/ts/blkid/low-probe
- - consolidate "getsize" stuff (see getsize.c and lib/blkdev.c)
-
- add values:
FSSIZE -- filesystem size (klibc requirement)
@@ -24,6 +18,11 @@ libblkid
...
blkid_unref(tp);
+blkid(8)
+
+ - add a new option (-r) that allows to print removable block devices that
+ are missing in /proc/partitions, see blkid_probe_all_removable().
+
wipefs
------
@@ -34,6 +33,11 @@ wipefs
fdisk(s)
--------
+ * 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
+ use geometry + BLKGETSIZE64 from kernel.
+
* use off_t instead "long long"
* catch SIGINT (Ctrl-C) and return to main menu.
@@ -52,6 +56,9 @@ fdisk(s)
misc
----
+ * partx: add to it an option to make it usable in shell scripts without having
+ to parse its output with sed
+
* use ngettext() for strings with plurals, for example
/* include/nls.h */
diff --git a/configure.ac b/configure.ac
index e36b8f6b..7fe2d111 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,6 +107,9 @@ AC_CHECK_HEADERS(
linux/fd.h \
linux/tiocl.h \
linux/version.h \
+ linux/falloc.h \
+ linux/cdrom.h \
+ fcntl.h \
locale.h \
stdint.h \
inttypes.h \
@@ -126,6 +129,8 @@ AC_CHECK_HEADERS(
sys/prctl.h \
sys/queue.h \
sys/sockio.h \
+ sys/socket.h \
+ sys/syscall.h \
sys/file.h \
sys/ioctl.h \
sys/stat.h \
@@ -140,9 +145,24 @@ AC_CHECK_HEADERS([linux/raw.h],
AC_CHECK_DECLS([_NL_TIME_WEEK_1STDAY],[],[],[[#include <langinfo.h>]])
+AC_CHECK_DECL([llseek],
+ [AC_DEFINE(HAVE_LLSEEK_PROTOTYPE, 1,
+ [Define to 1 if have llseek prototype])],
+ [],
+ [#include <unistd.h>])
+
+AC_CHECK_DECL([lseek64],
+ [AC_DEFINE(HAVE_LSEEK64_PROTOTYPE, 1,
+ [Define to 1 if have lseek64 prototype])],
+ [],
+ [#define _LARGEFILE_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #include <unistd.h>])
+
AC_CHECK_FUNCS(
[inet_aton \
futimens \
+ fstat64 \
fsync \
getdomainname \
get_current_dir_name \
@@ -431,6 +451,21 @@ fi
AM_CONDITIONAL(USE_SLANG, test "x$use_slang" = xyes)
+AC_ARG_WITH([utempter],
+ AS_HELP_STRING([--with-utempter], [compile script(1) with libutempter]),
+ [], with_utempter=no
+)
+
+if test "x$with_utempter" = xyes; then
+ UTIL_CHECK_LIB(utempter, utempter_add_record)
+ if test "x$have_utempter" = xno; then
+ AC_MSG_ERROR([utempter selected but libutempter not found])
+ fi
+else
+ AM_CONDITIONAL(HAVE_UTEMPTER, false)
+fi
+
+
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#define _XOPEN_SOURCE
#include <unistd.h>
@@ -563,7 +598,40 @@ UTIL_CHECK_SYSCALL([ioprio_get],
dnl fallocate could be available as libc function or as syscall only
UTIL_CHECK_SYSCALL([fallocate])
-AC_CHECK_FUNCS([fallocate])
+
+dnl check for valid fallocate() function
+dnl with 32 bits glibc 2.10, fallocate() exists but not fallocate64()
+dnl when _FILE_OFFSET_BITS==64, fallocate() is redirect to fallocate64()
+dnl and program can't be linked.
+dnl AC_CHECK_FUNC can't catch such errors since it's redefining
+dnl function prototype.
+AC_MSG_CHECKING([for valid fallocate() function])
+AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_LINUX_FALLOC_H
+# include <linux/falloc.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+]],[[
+ long ret;
+
+ ret = fallocate(0, FALLOC_FL_KEEP_SIZE, 0xfffffffful, 0xfffffffful);
+
+ if (ret != 0) {
+ return 1;
+ }
+ ]])],[
+AC_MSG_RESULT([yes])
+AC_DEFINE(HAVE_FALLOCATE,1,[Have valid fallocate() function])],[
+AC_MSG_RESULT([no])])
dnl unshare could be available as libc function or as syscall only
UTIL_CHECK_SYSCALL([unshare])
@@ -584,6 +652,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
AC_CHECK_MEMBERS([struct termios.c_line],,,
[[#include <termios.h>]])
+AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec],,,
+ [#include <sys/stat.h>])
+
AC_CHECK_DECLS([
ADDR_NO_RANDOMIZE,
FDPIC_FUNCPTRS,
diff --git a/disk-utils/.gitignore b/disk-utils/.gitignore
index 726008f6..c97b3421 100644
--- a/disk-utils/.gitignore
+++ b/disk-utils/.gitignore
@@ -10,3 +10,4 @@ mkswap
mkfs.cramfs
elvtune
raw
+swaplabel
diff --git a/disk-utils/Makefile.am b/disk-utils/Makefile.am
index ed0a6e4b..67aeae40 100644
--- a/disk-utils/Makefile.am
+++ b/disk-utils/Makefile.am
@@ -5,17 +5,32 @@ if LINUX
utils_common += ../lib/linux_version.c
endif
+if HAVE_UUID
+if BUILD_LIBUUID
+uuid_cflags = -I$(ul_libuuid_srcdir)
+uuid_ldadd = $(ul_libuuid_la)
+else
+uuid_cflags = $(UUID_CFLAGS)
+uuid_ldadd = $(UUID_LIBS)
+endif
+endif
+
dist_man_MANS = isosize.8 mkfs.8 mkswap.8 \
fsck.minix.8 mkfs.minix.8 mkfs.bfs.8
sbin_PROGRAMS = mkfs mkswap fsck.minix mkfs.minix mkfs.bfs
+
fsck_minix_SOURCES = fsck.minix.c minix.h
mkfs_minix_SOURCES = mkfs.minix.c minix.h $(utils_common)
mkfs_bfs_SOURCES = mkfs.bfs.c $(utils_common)
+swaplabel_SOURCES = swaplabel.c $(utils_common)
+swaplabel_LDADD = $(uuid_ldadd)
+swaplabel_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
+
mkswap_SOURCES = mkswap.c $(utils_common) ../lib/wholedisk.c
-mkswap_LDADD =
-mkswap_CFLAGS = $(AM_CFLAGS)
+mkswap_LDADD = $(uuid_ldadd)
+mkswap_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
usrbin_exec_PROGRAMS = isosize
usrsbin_exec_PROGRAMS =
@@ -27,6 +42,13 @@ usrsbin_exec_PROGRAMS += fdformat
blockdev_SOURCES = blockdev.c $(utils_common)
endif
+if BUILD_LIBBLKID
+sbin_PROGRAMS += swaplabel
+dist_man_MANS += swaplabel.8
+swaplabel_LDADD += $(ul_libblkid_la)
+swaplabel_CFLAGS += -I$(ul_libblkid_incdir)
+endif
+
if BUILD_ELVTUNE
sbin_PROGRAMS += elvtune
dist_man_MANS += elvtune.8
@@ -49,16 +71,6 @@ fsck_cramfs_LDADD = -lz
mkfs_cramfs_LDADD = -lz
endif
-if HAVE_UUID
-if BUILD_LIBUUID
-mkswap_LDADD += $(ul_libuuid_la)
-mkswap_CFLAGS += -I$(ul_libuuid_srcdir)
-else
-mkswap_LDADD += $(UUID_LIBS)
-mkswap_CFLAGS += $(UUID_CFLAGS)
-endif
-endif
-
if BUILD_LIBBLKID
# only in-tree libblkid has partitions parsing support
mkswap_LDADD += $(ul_libblkid_la)
diff --git a/disk-utils/blockdev.c b/disk-utils/blockdev.c
index 288c102d..eeaf2f5c 100644
--- a/disk-utils/blockdev.c
+++ b/disk-utils/blockdev.c
@@ -183,15 +183,15 @@ usage(void) {
fputc('\n', stderr);
fprintf(stderr, _("Available commands:\n"));
- fprintf(stderr, "\t%-30s %s\n", "--getsz",
+ fprintf(stderr, " %-25s %s\n", "--getsz",
_("get size in 512-byte sectors"));
for (i = 0; i < ARRAY_SIZE(bdcms); i++) {
if (bdcms[i].argname)
- fprintf(stderr, "\t%s %-*s %s\n", bdcms[i].name,
- (int) (29 - strlen(bdcms[i].name)),
+ fprintf(stderr, " %s %-*s %s\n", bdcms[i].name,
+ (int) (24 - strlen(bdcms[i].name)),
bdcms[i].argname, _(bdcms[i].help));
else
- fprintf(stderr, "\t%-30s %s\n", bdcms[i].name,
+ fprintf(stderr, " %-25s %s\n", bdcms[i].name,
_(bdcms[i].help));
}
fputc('\n', stderr);
diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c
index 1c72d07b..09a9a0a4 100644
--- a/disk-utils/mkswap.c
+++ b/disk-utils/mkswap.c
@@ -53,6 +53,7 @@
#include "blkdev.h"
#include "pathnames.h"
#include "wholedisk.h"
+#include "writeall.h"
#ifdef HAVE_LIBUUID
# ifdef HAVE_UUID_UUID_H
@@ -337,8 +338,6 @@ get_size(const char *file) {
}
if (blkdev_get_size(fd, &size) == 0)
size /= pagesize;
- else
- size = blkdev_find_size(fd) / pagesize;
close(fd);
return size;
@@ -372,26 +371,8 @@ check_mount(void) {
return 1;
}
-
-static int
-write_all(int fd, const void *buf, size_t count) {
- while(count) {
- ssize_t tmp;
-
- errno = 0;
- tmp = write(fd, buf, count);
- if (tmp > 0) {
- count -= tmp;
- if (count)
- buf += tmp;
- } else if (errno != EINTR && errno != EAGAIN)
- return -1;
- }
- return 0;
-}
-
static void
-zap_bootbits(int fd, const char *devname, int force)
+zap_bootbits(int fd, const char *devname, int force, int is_blkdev)
{
char *type = NULL;
int whole = 0;
@@ -401,7 +382,7 @@ zap_bootbits(int fd, const char *devname, int force)
if (lseek(fd, 0, SEEK_SET) != 0)
die(_("unable to rewind swap-device"));
- if (is_whole_disk_fd(fd, devname)) {
+ if (is_blkdev && is_whole_disk_fd(fd, devname)) {
/* don't zap bootbits on whole disk -- we know nothing
* about bootloaders on the device */
whole = 1;
@@ -561,13 +542,19 @@ main(int argc, char ** argv) {
usage();
}
if (block_count) {
- /* this silly user specified the number of blocks
- explicitly */
- char *tmp;
- int blocks_per_page = pagesize/1024;
- PAGES = strtoull(block_count,&tmp,0)/blocks_per_page;
- if (*tmp)
+ /* this silly user specified the number of blocks explicitly */
+ char *tmp = NULL;
+ long long blks;
+
+ errno = 0;
+ blks = strtoll(block_count, &tmp, 0);
+ if ((tmp == block_count) ||
+ (tmp && *tmp) ||
+ (errno != 0 && (blks == LLONG_MAX || blks == LLONG_MIN)) ||
+ blks < 0)
usage();
+
+ PAGES = blks / (pagesize / 1024);
}
sz = get_size(device_name);
if (!PAGES) {
@@ -638,7 +625,7 @@ main(int argc, char ** argv) {
if (check)
check_blocks();
- zap_bootbits(DEV, device_name, force);
+ zap_bootbits(DEV, device_name, force, S_ISBLK(statbuf.st_mode));
p->version = 1;
p->last_page = PAGES-1;
diff --git a/disk-utils/swaplabel.8 b/disk-utils/swaplabel.8
new file mode 100644
index 00000000..5c8b9e32
--- /dev/null
+++ b/disk-utils/swaplabel.8
@@ -0,0 +1,66 @@
+.\" Copyright 2010 Jason Borden <jborden@bluehost.com>
+.\"
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH SWAPLABEL 8 "2 April 2010" "Linux" "Linux Programmer's Manual"
+.SH NAME
+swaplabel \- Print or change the label / UUID of a swap area
+.SH SYNOPSIS
+.B swaplabel
+.RB [ \-L
+.IR label ]
+.RB [ \-U
+.IR UUID ]
+.I device
+.SH DESCRIPTION
+.B swaplabel
+will display or change the label / UUID of a swap partition located on
+.IR device
+(or regular file).
+.PP
+If the optional arguments
+.B \-L
+and
+.B \-U
+are not present,
+.B swaplabel
+will simply display the swap area label and UUID of
+.IR device .
+.PP
+If an optional argument is present, then
+.B swaplabel
+will change the appropriate value of
+.IR device .
+These values can also be set during swap creation using
+.BR mkswap (8).
+The
+.B swaplabel
+utility allows to change the label or UUID on actively used swap device.
+.SH OPTIONS
+.IP "\fB\-h, \-\-help\fP"
+Print help and exit.
+.IP "\fB\-L, \-\-label\fP \fIlabel\fP"
+Specify a new label for
+.IR device .
+Swap partition labels can be at most 16 characters long. If
+.IR label
+is longer than 16 characters,
+.B swapinfo
+will truncate it and print a warning message.
+.IP "\fB\-U, \-\-uuid\fP \fIuuid\fP"
+Specify a new UUID for
+.IR device .
+.IR UUID
+must be in the standard 8-4-4-4-12 character format, such as is ouput by
+.BR uuidgen (1) .
+.PP
+.SH AUTHOR
+.B swaplabel
+was written by Jason Borden <jborden@bluehost.com> and Karel Zak <kzak@redhat.com>.
+.SH AVAILABILITY
+.B swaplabel
+is part of the util-linux-ng package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
+.SH SEE ALSO
+.BR mkswap (8),
+.BR swapon (8),
+.BR uuidgen (1)
diff --git a/disk-utils/swaplabel.c b/disk-utils/swaplabel.c
new file mode 100644
index 00000000..63419722
--- /dev/null
+++ b/disk-utils/swaplabel.c
@@ -0,0 +1,226 @@
+/*
+ * swaplabel.c - Print or change the label / UUID of a swap partition
+ *
+ * Copyright (C) 2010 Jason Borden <jborden@bluehost.com>
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * Usage: swaplabel [-L label] [-U UUID] device
+ *
+ * This file may be redistributed under the terms of the GNU Public License
+ * version 2 or later.
+ *
+ */
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include <blkid.h>
+#include <getopt.h>
+
+#ifdef HAVE_LIBUUID
+# ifdef HAVE_UUID_UUID_H
+# include <uuid/uuid.h>
+# else
+# include <uuid.h>
+# endif
+#endif
+
+#include "c.h"
+#include "writeall.h"
+#include "swapheader.h"
+#include "xstrncpy.h"
+#include "nls.h"
+
+#define SWAP_UUID_OFFSET (offsetof(struct swap_header_v1_2, uuid))
+#define SWAP_LABEL_OFFSET (offsetof(struct swap_header_v1_2, volume_name))
+
+/*
+ * Returns new libblkid prober. This function call exit() on error.
+ */
+static blkid_probe get_swap_prober(const char *devname)
+{
+ blkid_probe pr;
+ int rc;
+ const char *version = NULL;
+ char *swap_filter[] = { "swap", NULL };
+
+ pr = blkid_new_probe_from_filename(devname);
+ if (!pr) {
+ warn(_("%s: unable to probe device"), devname);
+ return NULL;
+ }
+
+ blkid_probe_enable_superblocks(pr, TRUE);
+ blkid_probe_set_superblocks_flags(pr,
+ BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
+ BLKID_SUBLKS_VERSION);
+
+ blkid_probe_filter_superblocks_type(pr, BLKID_FLTR_ONLYIN, swap_filter);
+
+ rc = blkid_do_safeprobe(pr);
+ if (rc == -1)
+ warn(_("%s: unable to probe device"), devname);
+ else if (rc == -2)
+ warnx(_("%s: ambivalent probing result, use wipefs(8)"), devname);
+ else if (rc == 1)
+ warnx(_("%s: not a valid swap partition"), devname);
+
+ if (rc == 0) {
+ /* supported is SWAPSPACE2 only */
+ blkid_probe_lookup_value(pr, "VERSION", &version, NULL);
+ if (strcmp(version, "2"))
+ warnx(_("%s: unsupported swap version '%s'"),
+ devname, version);
+ else
+ return pr;
+ }
+
+ blkid_free_probe(pr);
+ return NULL;
+}
+
+/* Print the swap partition information */
+static int print_info(blkid_probe pr, const char *devname)
+{
+ const char *data;
+
+ if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
+ printf("LABEL: %s\n", data);
+
+ if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL))
+ printf("UUID: %s\n", data);
+
+ return 0;
+}
+
+/* Change the swap partition info */
+static int change_info(const char *devname, const char *label, const char *uuid)
+{
+ int fd;
+
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ warn(_("%s: failed to open"), devname);
+ goto err;
+ }
+#ifdef HAVE_LIBUUID
+ /* Write the uuid if it was provided */
+ if (uuid) {
+ uuid_t newuuid;
+
+ if (uuid_parse(uuid, newuuid) == -1)
+ warnx(_("failed to parse UUID: %s"), uuid);
+ else {
+ if (lseek(fd, SWAP_UUID_OFFSET, SEEK_SET) !=
+ SWAP_UUID_OFFSET) {
+ warn(_("%s: failed to seek to swap UUID"), devname);
+ goto err;
+
+ } else if (write_all(fd, newuuid, sizeof(newuuid))) {
+ warn(_("%s: failed to write UUID"), devname);
+ goto err;
+ }
+ }
+ }
+#endif
+ /* Write the label if it was provided */
+ if (label) {
+ char newlabel[SWAP_LABEL_LENGTH];
+
+ if (lseek(fd, SWAP_LABEL_OFFSET, SEEK_SET) != SWAP_LABEL_OFFSET) {
+ warn(_("%s: failed to seek to swap label "), devname);
+ goto err;
+ }
+ memset(newlabel, 0, sizeof(newlabel));
+ xstrncpy(newlabel, label, sizeof(newlabel));
+
+ if (strlen(label) > strlen(newlabel))
+ warnx(_("label is too long. Truncating it to '%s'"),
+ newlabel);
+ if (write_all(fd, newlabel, sizeof(newlabel))) {
+ warn(_("%s: failed to write label"), devname);
+ goto err;
+ }
+ }
+
+ close(fd);
+ return 0;
+err:
+ if (fd >= 0)
+ close(fd);
+ return -1;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+ fprintf(out, _("Usage: %s [options] <device>\n\nOptions:\n"),
+ program_invocation_short_name);
+
+ fprintf(out, _(
+ " -h, --help this help\n"
+ " -L, --label <label> specify a new label\n"
+ " -U, --uuid <uuid> specify a new uuid\n"));
+
+ fprintf(out, _("\nFor more information see swaplabel(8).\n"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ blkid_probe pr = NULL;
+ char *uuid = NULL, *label = NULL, *devname;
+ int c, rc = -1;
+
+ struct option longopts[] = {
+ { "help", 0, 0, 'h' },
+ { "label", 1, 0, 'L' },
+ { "uuid", 1, 0, 'U' },
+ { NULL, 0, 0, 0 }
+ };
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((c = getopt_long(argc, argv, "hL:U:", longopts, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ usage(stdout);
+ break;
+ case 'L':
+ label = optarg;
+ break;
+ case 'U':
+#ifdef HAVE_LIBUUID
+ uuid = optarg;
+#else
+ warnx(_("ignore -U (UUIDs are unsupported)"));
+#endif
+ break;
+ default:
+ usage(stderr);
+ break;
+ }
+ }
+
+ if (optind == argc)
+ usage(stderr);
+
+ devname = argv[optind];
+ pr = get_swap_prober(devname);
+ if (pr) {
+ if (uuid || label)
+ rc = change_info(devname, label, uuid);
+ else
+ rc = print_info(pr, devname);
+ blkid_free_probe(pr);
+ }
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am
index 50f1dbe8..7b87d6cf 100644
--- a/fdisk/Makefile.am
+++ b/fdisk/Makefile.am
@@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am
EXTRA_DIST = README.fdisk README.cfdisk sfdisk.examples partitiontype.c
fdisk_common = i386_sys_types.c common.h gpt.c gpt.h \
- ../lib/blkdev.c ../lib/wholedisk.c
+ ../lib/blkdev.c ../lib/wholedisk.c ../lib/mbsalign.c
if LINUX
fdisk_common += ../lib/linux_version.c
@@ -53,7 +53,7 @@ endif
if USE_SLANG
sbin_PROGRAMS += cfdisk
dist_man_MANS += cfdisk.8
-cfdisk_SOURCES = cfdisk.c $(fdisk_common)
+cfdisk_SOURCES = cfdisk.c $(fdisk_common) ../lib/mbsalign.c
cfdisk_CFLAGS = $(cflags_blkid)
cfdisk_LDADD = -lslang $(ldadd_blkid)
else
diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c
index eaf766c8..b1eaceeb 100644
--- a/fdisk/cfdisk.c
+++ b/fdisk/cfdisk.c
@@ -83,11 +83,16 @@
#include <blkid.h>
#endif
+#ifdef HAVE_WIDECHAR
+#include <wctype.h>
+#endif
+
#include "nls.h"
#include "blkdev.h"
#include "xstrncpy.h"
#include "common.h"
#include "gpt.h"
+#include "mbsalign.h"
#ifdef __GNU__
#define DEFAULT_DEVICE "/dev/hd0"
@@ -407,10 +412,10 @@ fdexit(int ret) {
static int
get_string(char *str, int len, char *def) {
- unsigned char c;
- int i = 0;
- int x, y;
+ size_t cells = 0, i = 0;
+ int x, y, key;
int use_def = FALSE;
+ wint_t c;
getyx(stdscr, y, x);
clrtoeol();
@@ -424,7 +429,13 @@ get_string(char *str, int len, char *def) {
}
refresh();
+
+#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
+ while ((key = get_wch(&c)) != ERR &&
+ c != '\r' && c != '\n' && c != KEY_ENTER) {
+#else
while ((c = getch()) != '\n' && c != CR) {
+#endif
switch (c) {
case ESC:
move(y, x);
@@ -433,10 +444,14 @@ get_string(char *str, int len, char *def) {
return GS_ESCAPE;
case DEL:
case '\b':
+ case KEY_BACKSPACE:
if (i > 0) {
- str[--i] = 0;
- mvaddch(y, x+i, ' ');
- move(y, x+i);
+ cells--;
+ i = mbs_truncate(str, &cells);
+ if (i < 0)
+ return GS_ESCAPE;
+ mvaddch(y, x + cells, ' ');
+ move(y, x + cells);
} else if (use_def) {
clrtoeol();
use_def = FALSE;
@@ -444,15 +459,39 @@ get_string(char *str, int len, char *def) {
putchar(BELL);
break;
default:
+#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
+ if (i < len && iswprint(c)) {
+ wchar_t wc = (wchar_t) c;
+ char s[MB_CUR_MAX + 1];
+ int sz = wctomb(s, wc);
+
+ if (sz + i < len) {
+ s[sz] = '\0';
+ mvaddnstr(y, x + cells, s, sz);
+ if (use_def) {
+ clrtoeol();
+ use_def = FALSE;
+ }
+ memcpy(str + i, s, sz);
+ i += sz;
+ str[i] = '\0';
+ cells += wcwidth(wc);
+ } else
+ putchar(BELL);
+ }
+#else
if (i < len && isprint(c)) {
- mvaddch(y, x+i, c);
+ mvaddch(y, x + cells, c);
if (use_def) {
clrtoeol();
use_def = FALSE;
}
str[i++] = c;
str[i] = 0;
- } else
+ cells++;
+ }
+#endif
+ else
putchar(BELL);
}
refresh();
@@ -2584,6 +2623,7 @@ static void
do_curses_fdisk(void) {
int done = FALSE;
char command;
+ int is_first_run = TRUE;
static struct MenuItem menuMain[] = {
{ 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") },
@@ -2626,16 +2666,17 @@ do_curses_fdisk(void) {
if (p_info[cur_part].id == FREE_SPACE) {
s = ((opentype == O_RDWR) ? "hnpquW" : "hnpqu");
command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
- s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0);
+ s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 5);
} else if (p_info[cur_part].id > 0) {
s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu");
command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
- s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0);
+ s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, is_first_run ? 7 : 0);
} else {
s = ((opentype == O_RDWR) ? "hpquW" : "hpqu");
command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0);
}
+ is_first_run = FALSE;
switch ( command ) {
case 'B':
case 'b':
diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8
index c04972f6..30dc9678 100644
--- a/fdisk/fdisk.8
+++ b/fdisk/fdisk.8
@@ -6,7 +6,7 @@
fdisk \- Partition table manipulator for Linux
.SH SYNOPSIS
.B fdisk
-.RB [ \-u ]
+.RB [ \-uc ]
.RB [ \-b
.IR sectorsize ]
.RB [ \-C
@@ -25,6 +25,8 @@ fdisk \- Partition table manipulator for Linux
.IR partition ...
.sp
.B fdisk \-v
+.sp
+.B fdisk \-h
.SH DESCRIPTION
Hard disks can be divided into one or more logical disks called
.IR partitions .
@@ -180,7 +182,15 @@ program and Linux partitions with the Linux fdisk or Linux cfdisk program.
.BI "\-b " sectorsize
Specify the sector size of the disk. Valid values are 512, 1024, 2048 or 4096.
(Recent kernels know the sector size. Use this only on old kernels or
-to override the kernel's ideas.)
+to override the kernel's ideas.) Since util-linux-ng 2.17 fdisk differentiates
+between logical and physical sector size. This option changes both sector sizes to
+.IB sectorsize .
+.TP
+.BI \-h
+Print help and then exit.
+.TP
+.BI \-c
+Switch off DOS-compatible mode. (Recommended)
.TP
.BI "\-C " cyls
Specify the number of cylinders of the disk.
diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index cc573646..0126e67b 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -25,6 +25,7 @@
#include "nls.h"
#include "blkdev.h"
#include "common.h"
+#include "mbsalign.h"
#include "fdisk.h"
#include "wholedisk.h"
@@ -222,7 +223,12 @@ unsigned int heads,
display_in_cyl_units = 1;
unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */
-unsigned long io_size, alignment_offset;
+unsigned long grain = DEFAULT_SECTOR_SIZE,
+ io_size = DEFAULT_SECTOR_SIZE,
+ min_io_size = DEFAULT_SECTOR_SIZE,
+ phy_sector_size = DEFAULT_SECTOR_SIZE,
+ alignment_offset;
+int has_topology;
#define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label)
int sun_label = 0; /* looking at sun disklabel */
@@ -237,6 +243,7 @@ jmp_buf listingbuf;
void fatal(enum failure why) {
char error[LINE_LENGTH],
*message = error;
+ int rc = EXIT_FAILURE;
if (listing) {
close(fd);
@@ -244,25 +251,23 @@ void fatal(enum failure why) {
}
switch (why) {
+ case help:
+ rc = EXIT_SUCCESS;
case usage: message = _(
-"Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
-" fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
-" fdisk -s PARTITION Give partition size(s) in blocks\n"
-" fdisk -v Give fdisk version\n"
-"Here DISK is something like /dev/hdb or /dev/sda\n"
-"and PARTITION is something like /dev/hda7\n"
-"-u: give Start and End in sector (instead of cylinder) units\n"
-"-b 2048: (for certain MO disks) use 2048-byte sectors\n");
- break;
- case usage2:
- /* msg in cases where fdisk used to probe */
- message = _(
-"Usage: fdisk [-l] [-b SSZ] [-u] device\n"
-"E.g.: fdisk /dev/hda (for the first IDE disk)\n"
-" or: fdisk /dev/sdc (for the third SCSI disk)\n"
-" or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
-" or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
-" ...\n");
+"Usage:\n"
+" fdisk [options] <disk> change partition table\n"
+" fdisk [options] -l <disk> list partition table(s)\n"
+" fdisk -s <partition> give partition size(s) in blocks\n"
+"\nOptions:\n"
+" -b <size> sector size (512, 1024, 2048 or 4096)\n"
+" -c switch off DOS-compatible mode\n"
+" -h print help\n"
+" -u <size> give sizes in sectors instead of cylinders\n"
+" -v print version\n"
+" -C <number> specify the number of cylinders\n"
+" -H <number> specify the number of heads\n"
+" -S <number> specify the number of sectors per track\n"
+"\n");
break;
case unable_to_open:
snprintf(error, sizeof(error),
@@ -294,7 +299,7 @@ void fatal(enum failure why) {
fputc('\n', stderr);
fputs(message, stderr);
- exit(1);
+ exit(rc);
}
static void
@@ -564,9 +569,19 @@ void list_types(struct systypes *sys)
i = done = 0;
do {
- printf("%c%2x %-15.15s", i ? ' ' : '\n',
- sys[next].type, _(sys[next].name));
- next = last[i++] + done;
+ #define NAME_WIDTH 15
+ char name[NAME_WIDTH * MB_LEN_MAX];
+ size_t width = NAME_WIDTH;
+
+ printf("%c%2x ", i ? ' ' : '\n', sys[next].type);
+ size_t ret = mbsalign(_(sys[next].name), name, sizeof(name),
+ &width, MBS_ALIGN_LEFT, 0);
+ if (ret == (size_t)-1 || ret >= sizeof(name))
+ printf("%-15.15s", _(sys[next].name));
+ else
+ fputs(name, stdout);
+
+ next = last[i++] + done;
if (i > 3 || next >= last[i]) {
i = 0;
next = ++done;
@@ -637,17 +652,15 @@ test_c(char **m, char *mesg) {
return val;
}
-#define alignment_required (io_size != sector_size)
+#define alignment_required (grain != sector_size)
static int
lba_is_aligned(unsigned long long lba)
{
- unsigned long long bytes, phy_sectors;
+ unsigned int granularity = max(phy_sector_size, min_io_size);
+ unsigned long long offset = (lba << 9) & (granularity - 1);
- bytes = lba * sector_size;
- phy_sectors = bytes / io_size;
-
- return (alignment_offset + (phy_sectors * io_size) == bytes);
+ return !((granularity + alignment_offset - offset) & (granularity - 1));
}
#define ALIGN_UP 1
@@ -657,39 +670,52 @@ lba_is_aligned(unsigned long long lba)
static unsigned long long
align_lba(unsigned long long lba, int direction)
{
- unsigned long long sects_in_phy, res;
+ unsigned long long res;
if (lba_is_aligned(lba))
- return lba;
+ res = lba;
+ else {
+ unsigned long long sects_in_phy = grain / sector_size;
- sects_in_phy = io_size / sector_size;
+ if (lba < sector_offset)
+ res = sector_offset;
- if (lba < sects_in_phy)
- /* align to the first physical sector */
- res = sects_in_phy;
+ else if (direction == ALIGN_UP)
+ res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
- else if (direction == ALIGN_UP)
- res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
+ else if (direction == ALIGN_DOWN)
+ res = (lba / sects_in_phy) * sects_in_phy;
- else if (direction == ALIGN_DOWN)
- res = (lba / sects_in_phy) * sects_in_phy;
+ else /* ALIGN_NEAREST */
+ res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
- else /* ALIGN_NEAREST */
- res = ((lba + sects_in_phy/2) / sects_in_phy) * sects_in_phy;
+ if (alignment_offset && !lba_is_aligned(res) &&
+ res > alignment_offset / sector_size) {
+ /*
+ * apply alignment_offset
+ *
+ * On disk with alignment compensation physical blocks starts
+ * at LBA < 0 (usually LBA -1). It means we have to move LBA
+ * according the offset to be on the physical boundary.
+ */
+ /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */
+ res -= (max(phy_sector_size, min_io_size) -
+ alignment_offset) / sector_size;
- if (alignment_offset)
- /*
- * apply alignment_offset
- *
- * On disk with alignment compensation physical blocks start
- * at LBA < 0 (usually LBA -1). It means we have to move LBA
- * according the offset to be on the physical boundary.
- */
- res -= (io_size - alignment_offset) / sector_size;
+ if (direction == ALIGN_UP && res < lba)
+ res += sects_in_phy;
+ }
+ }
- /* fprintf(stderr, "LBA %llu -align-> %llu (%s)\n", lba, res,
- * lba_is_aligned(res) ? "OK" : "FALSE");
- */
+ /***
+ fprintf(stderr, "LBA %llu (%s) --align-(%s)--> %llu (%s)\n",
+ lba,
+ lba_is_aligned(lba) ? "OK" : "FALSE",
+ direction == ALIGN_UP ? "UP " :
+ direction == ALIGN_DOWN ? "DOWN " : "NEAREST",
+ res,
+ lba_is_aligned(res) ? "OK" : "FALSE");
+ ***/
return res;
}
@@ -742,19 +768,6 @@ void update_units(void)
}
static void
-warn_cylinders(void) {
- if (dos_label && cylinders > 1024 && !nowarn)
- fprintf(stderr, _("\n"
-"The number of cylinders for this disk is set to %d.\n"
-"There is nothing wrong with that, but this is larger than 1024,\n"
-"and could in certain setups cause problems with:\n"
-"1) software that runs at boot time (e.g., old versions of LILO)\n"
-"2) booting and partitioning software from other OSs\n"
-" (e.g., DOS FDISK, OS/2 FDISK)\n"),
- cylinders);
-}
-
-static void
warn_limits(void) {
if (total_number_of_sectors > UINT_MAX && !nowarn) {
int giga = (total_number_of_sectors << 9) / 1000000000;
@@ -774,28 +787,30 @@ warn_limits(void) {
static void
warn_alignment(void) {
- if (nowarn || !alignment_required)
+ if (nowarn)
return;
- fprintf(stderr, _("\n"
+ if (sector_size != phy_sector_size)
+ fprintf(stderr, _("\n"
"The device presents a logical sector size that is smaller than\n"
-"the optimal I/O size (often physical sector size). Aligning to a optimal\n"
-"I/O size boundary is recommended, or performance may be impacted.\n\n"));
+"the physical sector size. Aligning to a physical sector (or optimal\n"
+"I/O) size boundary is recommended, or performance may be impacted.\n"));
- /*
- * Print warning when sector_offset is not aligned for DOS mode
- */
- if (alignment_offset == 0 && dos_compatible_flag &&
- !lba_is_aligned(sector_offset))
+ if (dos_compatible_flag) {
+ fprintf(stderr, _("\n"
+"WARNING: DOS-compatible mode is deprecated. It's strongly recommended to\n"
+" switch off the mode (command 'c')"));
- fprintf(stderr, _(
-"WARNING: The device does not provide compensation (alignment_offset)\n"
-"for DOS-compatible partitioning, but DOS-compatible mode is enabled.\n"
-"Use command 'c' to switch-off DOS mode.\n\n"));
+ if (display_in_cyl_units)
+ fprintf(stderr, _(" and change display units to\n"
+" sectors (command 'u').\n"));
+ else
+ fprintf(stderr, ".\n");
- if (display_in_cyl_units)
- fprintf(stderr, _(
-"It's recommended to change display units to sectors (command 'u').\n\n"));
+ } else if (display_in_cyl_units)
+ fprintf(stderr, _("\n"
+"WARNING: cylinders as display units are deprecated. Use command 'u' to\n"
+" change units to sectors.\n"));
}
@@ -961,29 +976,52 @@ get_topology(int fd) {
#ifdef HAVE_LIBBLKID_INTERNAL
blkid_probe pr;
- if (user_set_sector_size)
- return;
pr = blkid_new_probe();
if (pr && blkid_probe_set_device(pr, fd, 0, 0) == 0) {
blkid_topology tp = blkid_probe_get_topology(pr);
if (tp) {
+ min_io_size = blkid_topology_get_minimum_io_size(tp);
io_size = blkid_topology_get_optimal_io_size(tp);
- if (!io_size)
- io_size = blkid_topology_get_minimum_io_size(tp);
+ phy_sector_size = blkid_topology_get_physical_sector_size(tp);
alignment_offset = blkid_topology_get_alignment_offset(tp);
+
+ /* We assume that the device provides topology info if
+ * optimal_io_size is set or alignment_offset is set or
+ * minimum_io_size is not power of 2.
+ *
+ * See also update_sector_offset().
+ */
+ if (io_size || alignment_offset ||
+ (min_io_size & (min_io_size - 1)))
+ has_topology = 1;
+ if (!io_size)
+ /* optimal IO is optional, default to minimum IO */
+ io_size = min_io_size;
}
}
blkid_free_probe(pr);
#endif
if (user_set_sector_size)
- ;
- else if (blkdev_get_sector_size(fd, &arg) == 0)
+ /* fdisk since 2.17 differentiate between logical and physical
+ * sectors size. For backward compatibility the
+ * fdisk -b <sectorsize>
+ * changes both, logical and physical sector size.
+ */
+ phy_sector_size = sector_size;
+
+ else if (blkdev_get_sector_size(fd, &arg) == 0) {
sector_size = arg;
+ if (!phy_sector_size)
+ phy_sector_size = sector_size;
+ }
+
+ if (!min_io_size)
+ min_io_size = phy_sector_size;
if (!io_size)
- io_size = sector_size;
+ io_size = min_io_size;
if (sector_size != DEFAULT_SECTOR_SIZE)
printf(_("Note: sector size is %d (not %d)\n"),
@@ -1041,24 +1079,47 @@ get_partition_table_geometry(void) {
void
update_sector_offset(void)
{
- if (dos_compatible_flag) {
- /* usually 63 sectors for classic geometry */
- sector_offset = sectors;
+ grain = io_size;
- /* On the disks with alignment_offset the default geo.sectors
- * has to be aligned to physical block boundary. Check it!
- */
- if (sectors && alignment_offset && !lba_is_aligned(sectors))
- fprintf(stderr, _(
- "\nWARNING: the device provides alignment_offset, but the offset does not\n"
- "match with device geometry.\n\n"));
- } else {
+ if (dos_compatible_flag)
+ sector_offset = sectors; /* usually 63 sectors */
+ else {
/*
- * Align the begin of the first partition to the physical block
+ * Align the begin of partitions to:
+ *
+ * a) topology
+ * a2) alignment offset
+ * a1) or physical sector (minimal_io_size, aka "grain")
+ *
+ * b) or default to 1MiB (2048 sectrors, Windows Vista default)
+ *
+ * c) or for very small devices use 1 phy.sector
*/
- unsigned long long x = io_size / sector_size;
+ unsigned long long x = 0;
+
+ if (has_topology) {
+ if (alignment_offset)
+ x = alignment_offset;
+ else if (io_size > 2048 * 512)
+ x = io_size;
+ }
+ /* default to 1MiB */
+ if (!x)
+ x = 2048 * 512;
+
+ sector_offset = x / sector_size;
+
+ /* don't use huge offset on small devices */
+ if (total_number_of_sectors <= sector_offset * 4)
+ sector_offset = phy_sector_size / sector_size;
- sector_offset = align_lba(x, ALIGN_UP);
+ /* use 1MiB grain always when possible */
+ if (grain < 2048 * 512)
+ grain = 2048 * 512;
+
+ /* don't use huge grain on small devices */
+ if (total_number_of_sectors <= (grain * 4 / sector_size))
+ grain = phy_sector_size;
}
}
@@ -1249,7 +1310,6 @@ got_dos_table:
}
}
- warn_cylinders();
warn_geometry();
warn_limits();
warn_alignment();
@@ -1462,11 +1522,11 @@ read_int(unsigned int low, unsigned int dflt, unsigned int high,
int
-get_partition(int warn, int max) {
+get_partition_dflt(int warn, int max, int dflt) {
struct pte *pe;
int i;
- i = read_int(1, 0, max, 0, _("Partition number")) - 1;
+ i = read_int(1, dflt, max, 0, _("Partition number")) - 1;
pe = &ptes[i];
if (warn) {
@@ -1483,6 +1543,11 @@ get_partition(int warn, int max) {
return i;
}
+int
+get_partition(int warn, int max) {
+ return get_partition_dflt(warn, max, 0);
+}
+
static int
get_existing_partition(int warn, int max) {
int pno = -1;
@@ -1513,14 +1578,17 @@ static int
get_nonexisting_partition(int warn, int max) {
int pno = -1;
int i;
+ int dflt = 0;
for (i = 0; i < max; i++) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
if (p && is_cleared_partition(p)) {
- if (pno >= 0)
+ if (pno >= 0) {
+ dflt = pno + 1;
goto not_unique;
+ }
pno = i;
}
}
@@ -1532,7 +1600,7 @@ get_nonexisting_partition(int warn, int max) {
return -1;
not_unique:
- return get_partition(warn, max);
+ return get_partition_dflt(warn, max, dflt);
}
const char *
@@ -1751,6 +1819,9 @@ static void check_consistency(struct partition *p, int partition) {
unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */
unsigned int lec, leh, les; /* logical ending c, h, s */
+ if (!dos_compatible_flag)
+ return;
+
if (!heads || !sectors || (partition >= 4))
return; /* do not check extended partitions */
@@ -1809,10 +1880,10 @@ static void check_consistency(struct partition *p, int partition) {
}
static void
-check_alignment(struct partition *p, int partition)
+check_alignment(unsigned long long lba, int partition)
{
- if (!lba_is_aligned(get_start_sect(p)))
- printf(_("Partition %i does not start on optimal I/O size boundary.\n"),
+ if (!lba_is_aligned(lba))
+ printf(_("Partition %i does not start on physical sector boundary.\n"),
partition + 1);
}
@@ -1839,8 +1910,10 @@ list_disk_geometry(void) {
str_units(PLURAL),
units_per_sector, sector_size, units_per_sector * sector_size);
- printf(_("Sector size (logical / optimal IO): %u bytes / %lu bytes\n"),
- sector_size, io_size);
+ printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"),
+ sector_size, phy_sector_size);
+ printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"),
+ min_io_size, io_size);
if (alignment_offset)
printf(_("Alignment offset: %lu bytes\n"), alignment_offset);
if (dos_label)
@@ -2051,7 +2124,7 @@ list_table(int xtra) {
/* type name */ (type = partition_type(p->sys_ind)) ?
type : _("Unknown"));
check_consistency(p, i);
- check_alignment(p, i);
+ check_alignment(get_partition_start(pe), i);
}
}
@@ -2086,7 +2159,7 @@ x_list_table(int extend) {
(unsigned long) get_nr_sects(p), p->sys_ind);
if (p->sys_ind) {
check_consistency(p, i);
- check_alignment(p, i);
+ check_alignment(get_partition_start(pe), i);
}
}
}
@@ -2164,7 +2237,7 @@ verify(void) {
p = pe->part_table;
if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
check_consistency(p, i);
- check_alignment(p, i);
+ check_alignment(get_partition_start(pe), i);
if (get_partition_start(pe) < first[i])
printf(_("Warning: bad start-of-data in "
"partition %d\n"), i + 1);
@@ -2273,17 +2346,16 @@ add_partition(int n, int sys) {
snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
do {
- unsigned long long dflt, dflt_tmp;
+ unsigned long long dflt, aligned;
temp = start;
-
dflt = start = get_unused_start(n, start, first, last);
/* the default sector should be aligned and unused */
do {
- dflt_tmp = align_lba_in_range(dflt, start, limit);
- dflt = get_unused_start(n, dflt_tmp, first, last);
- } while (dflt != dflt_tmp && dflt > dflt_tmp && dflt < limit);
+ aligned = align_lba_in_range(dflt, dflt, limit);
+ dflt = get_unused_start(n, aligned, first, last);
+ } while (dflt != aligned && dflt > aligned && dflt < limit);
if (dflt >= limit)
dflt = start;
@@ -2590,7 +2662,8 @@ static void
move_begin(int i) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
- unsigned int new, first;
+ unsigned int new, free_start, curr_start, last;
+ int x;
if (warn_geometry())
return;
@@ -2598,13 +2671,37 @@ move_begin(int i) {
printf(_("Partition %d has no data area\n"), i + 1);
return;
}
- first = get_partition_start(pe);
- new = read_int(first, first, first + get_nr_sects(p) - 1, first,
+
+ /* the default start is at the second sector of the disk or at the
+ * second sector of the extended partition
+ */
+ free_start = pe->offset ? pe->offset + 1 : 1;
+
+ curr_start = get_partition_start(pe);
+
+ /* look for a free space before the current start of the partition */
+ for (x = 0; x < partitions; x++) {
+ unsigned int end;
+ struct pte *prev_pe = &ptes[x];
+ struct partition *prev_p = prev_pe->part_table;
+
+ if (!prev_p)
+ continue;
+ end = get_partition_start(prev_pe) + get_nr_sects(prev_p);
+
+ if (!is_cleared_partition(prev_p) &&
+ end > free_start && end <= curr_start)
+ free_start = end;
+ }
+
+ last = get_partition_start(pe) + get_nr_sects(p) - 1;
+
+ new = read_int(free_start, curr_start, last, free_start,
_("New beginning of data")) - pe->offset;
if (new != get_nr_sects(p)) {
- first = get_nr_sects(p) + get_start_sect(p) - new;
- set_nr_sects(p, first);
+ unsigned int sects = get_nr_sects(p) + get_start_sect(p) - new;
+ set_nr_sects(p, sects);
set_start_sect(p, new);
pe->changed = 1;
}
@@ -2632,8 +2729,6 @@ xselect(void) {
_("Number of cylinders"));
if (sun_label)
sun_set_ncyl(cylinders);
- if (dos_label)
- warn_cylinders();
break;
case 'd':
print_raw();
@@ -2830,17 +2925,7 @@ main(int argc, char **argv) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- /*
- * Calls:
- * fdisk -v
- * fdisk -l [-b sectorsize] [-u] device ...
- * fdisk -s [partition] ...
- * fdisk [-b sectorsize] [-u] device
- *
- * Options -C, -H, -S set the geometry.
- *
- */
- while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
+ while ((c = getopt(argc, argv, "b:cC:hH:lsS:uvV")) != -1) {
switch (c) {
case 'b':
/* Ugly: this sector size is really per device,
@@ -2857,6 +2942,12 @@ main(int argc, char **argv) {
case 'C':
user_cylinders = atoi(optarg);
break;
+ case 'c':
+ dos_compatible_flag = 0;
+ break;
+ case 'h':
+ fatal(help);
+ break;
case 'H':
user_heads = atoi(optarg);
if (user_heads <= 0 || user_heads > 256)
@@ -2942,10 +3033,8 @@ main(int argc, char **argv) {
if (argc-optind == 1)
disk_device = argv[optind];
- else if (argc-optind != 0)
- fatal(usage);
else
- fatal(usage2);
+ fatal(usage);
gpt_warning(disk_device);
get_boot(fdisk);
diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h
index 0286ce0a..1a89beb9 100644
--- a/fdisk/fdisk.h
+++ b/fdisk/fdisk.h
@@ -45,7 +45,7 @@ struct partition {
unsigned char size4[4]; /* nr of sectors in partition */
} PACKED;
-enum failure {usage, usage2, ioctl_error,
+enum failure {help, usage, ioctl_error,
unable_to_open, unable_to_read, unable_to_seek,
unable_to_write, out_of_memory};
diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c
index 2f415616..9c092524 100644
--- a/fdisk/fdiskbsdlabel.c
+++ b/fdisk/fdiskbsdlabel.c
@@ -540,7 +540,7 @@ xbsd_write_bootstrap (void)
memmove (&dl, d, sizeof (struct xbsd_disklabel));
/* The disklabel will be overwritten by 0's from bootxx anyway */
- bzero (d, sizeof (struct xbsd_disklabel));
+ memset (d, 0, sizeof (struct xbsd_disklabel));
snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
@@ -656,7 +656,7 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
struct geom g;
get_geometry (fd, &g);
- bzero (d, sizeof (struct xbsd_disklabel));
+ memset (d, 0, sizeof (struct xbsd_disklabel));
d -> d_magic = BSD_DISKMAGIC;
diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c
index 670a15a5..68596eea 100644
--- a/fdisk/fdisksunlabel.c
+++ b/fdisk/fdisksunlabel.c
@@ -146,17 +146,17 @@ int check_sun_label(void)
if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"),
- sunlabel->version);
+ SSWAP32(sunlabel->version));
need_fixing = 1;
}
if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) {
fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"),
- sunlabel->sanity);
+ SSWAP32(sunlabel->sanity));
need_fixing = 1;
}
if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) {
fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"),
- sunlabel->num_partitions);
+ SSWAP16(sunlabel->num_partitions));
need_fixing = 1;
}
if (need_fixing) {
@@ -186,8 +186,8 @@ void create_sunlabel(void)
{
struct hd_geometry geometry;
unsigned long long llsectors, llcyls;
- unsigned int ndiv;
- int res, sec_fac;
+ unsigned int ndiv, sec_fac;
+ int res;
fprintf(stderr,
_("Building a new sun disklabel. Changes will remain in memory only,\n"
@@ -573,8 +573,8 @@ void sun_list_table(int xtra)
w = strlen(disk_device);
if (xtra)
printf(
- _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n"
- "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
+ _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %d rpm\n"
+ "%u cylinders, %d alternate cylinders, %d physical cylinders\n"
"%d extra sects/cyl, interleave %d:1\n"
"Label ID: %s\n"
"Volume ID: %s\n"
@@ -589,7 +589,7 @@ void sun_list_table(int xtra)
str_units(PLURAL), units_per_sector);
else
printf(
- _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d cylinders\n"
+ _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %u cylinders\n"
"Units = %s of %d * 512 bytes\n\n"),
disk_device, heads, sectors, cylinders,
str_units(PLURAL), units_per_sector);
@@ -604,13 +604,13 @@ void sun_list_table(int xtra)
uint32_t start = SSWAP32(part->start_cylinder) * heads * sectors;
uint32_t len = SSWAP32(part->num_sectors);
printf(
- "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
+ "%s %c%c %9lu %9lu %9lu%c %2x %s\n",
/* device */ partname(disk_device, i+1, w),
/* flags */ (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ',
(tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ',
-/* start */ (long) scround(start),
-/* end */ (long) scround(start+len),
-/* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
+/* start */ (unsigned long) scround(start),
+/* end */ (unsigned long) scround(start+len),
+/* odd flag on end */ (unsigned long) len / 2, len & 1 ? '+' : ' ',
/* type id */ SSWAP16(tag->tag),
/* type name */ (type = partition_type(SSWAP16(tag->tag)))
? type : _("Unknown"));
diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c
index 6ac91f07..6432b25c 100644
--- a/fdisk/sfdisk.c
+++ b/fdisk/sfdisk.c
@@ -1637,6 +1637,11 @@ write_partitions(char *dev, int fd, struct disk_desc *z) {
error(_("Failed writing the partition on %s\n"), dev);
return 0;
}
+ if (fsync(fd)) {
+ perror(dev);
+ error(_("Failed writing the partition on %s\n"), dev);
+ return 0;
+ }
return 1;
}
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 45d8484a..7577eff1 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -37,7 +37,6 @@
#include <string.h>
#include <time.h>
#include <stdlib.h>
-#include <errno.h>
#include <paths.h>
#include <unistd.h>
#include <errno.h>
diff --git a/hwclock/hwclock.8 b/hwclock/hwclock.8
index dc21acd7..8c6b2406 100644
--- a/hwclock/hwclock.8
+++ b/hwclock/hwclock.8
@@ -132,6 +132,13 @@ For example, on a Digital Unix machine:
.sp
.I hwclock --setepoch --epoch=1952
+.TP
+.BI \-\-predict
+Predict what the RTC will read at time given by the
+.B \-\-date
+option based on the adjtime file. This is useful for example if you
+need to set an RTC wakeup time to distant future and want to account
+for the RTC drift.
.SH OPTIONS
.PP
diff --git a/hwclock/hwclock.c b/hwclock/hwclock.c
index ac1f7c86..4f32aa82 100644
--- a/hwclock/hwclock.c
+++ b/hwclock/hwclock.c
@@ -1134,7 +1134,7 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
const bool hctosys, const bool systohc, const bool systz,
const struct timeval startup_time,
const bool utc, const bool local_opt,
- const bool testing) {
+ const bool testing, const bool predict) {
/*---------------------------------------------------------------------------
Do all the normal work of hwclock - read, set clock, etc.
@@ -1147,13 +1147,13 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
int rc; /* local return code */
bool no_auth; /* User lacks necessary authorization to access the clock */
- if (!systz) {
+ if (!systz && !predict) {
no_auth = ur->get_permissions();
if (no_auth)
return EX_NOPERM;
}
- if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt))) {
+ if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt) || predict)) {
rc = read_adjtime(&adjtime);
if (rc)
return rc;
@@ -1187,7 +1187,7 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
Defined only if hclock_valid is true.
*/
- if (show || adjust || hctosys || (!noadjfile && !systz)) {
+ if (show || adjust || hctosys || (!noadjfile && !systz && !predict)) {
/* data from HW-clock are required */
rc = synchronize_to_clock_tick();
if (rc && rc != 2) /* 2= synchronization timeout */
@@ -1237,6 +1237,20 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
printf(_("Unable to set system clock.\n"));
return rc;
}
+ } else if (predict) {
+ int adjustment;
+ double retro;
+
+ calculate_adjustment(adjtime.drift_factor,
+ adjtime.last_adj_time,
+ adjtime.not_adjusted,
+ set_time,
+ &adjustment, &retro);
+ if (debug) {
+ printf(_("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"),
+ set_time, set_time + adjustment);
+ }
+ display_time(TRUE, set_time + adjustment, -retro);
}
if (!noadjfile)
save_adjtime(adjtime, testing);
@@ -1332,6 +1346,7 @@ usage( const char *fmt, ... ) {
" --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"
+ " --predict predict rtc reading at time given with --date\n"
" -v | --version print out the version of hwclock to stdout\n"
"\nOptions: \n"
" -u | --utc the hardware clock is kept in UTC\n"
@@ -1401,6 +1416,7 @@ static const struct option longopts[] = {
{ "rtc", 1, 0, 'f' },
{ "adjfile", 1, 0, 138 },
{ "systz", 0, 0, 139 },
+ { "predict-hc", 0, 0, 140 },
{ NULL, 0, 0, 0 }
};
@@ -1426,7 +1442,7 @@ main(int argc, char **argv) {
/* Variables set by various options; show may also be set later */
/* The options debug, badyear and epoch_option are global */
- bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch;
+ bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch, predict;
bool utc, testing, local_opt, noadjfile, directisa;
bool ARCconsole, Jensen, SRM, funky_toy;
char *date_opt;
@@ -1456,7 +1472,7 @@ main(int argc, char **argv) {
textdomain(PACKAGE);
/* Set option defaults */
- show = set = systohc = hctosys = systz = adjust = noadjfile = FALSE;
+ show = set = systohc = hctosys = systz = adjust = noadjfile = predict = FALSE;
getepoch = setepoch = utc = local_opt = testing = debug = FALSE;
ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
date_opt = NULL;
@@ -1532,6 +1548,9 @@ main(int argc, char **argv) {
case 139:
systz = TRUE; /* --systz */
break;
+ case 140:
+ predict = TRUE; /* --predict-hc */
+ break;
case 'f':
rtc_dev_name = optarg; /* --rtc */
break;
@@ -1564,7 +1583,7 @@ main(int argc, char **argv) {
}
if (show + set + systohc + hctosys + systz + adjust + getepoch
- + setepoch > 1){
+ + setepoch + predict > 1){
fprintf(stderr, _("You have specified multiple functions.\n"
"You can only perform one function "
"at a time.\n"));
@@ -1605,7 +1624,7 @@ main(int argc, char **argv) {
set_cmos_access(Jensen, funky_toy);
#endif
- if (set) {
+ if (set || predict) {
rc = interpret_date_string(date_opt, &set_time);
/* (time-consuming) */
if (rc != 0) {
@@ -1616,7 +1635,7 @@ main(int argc, char **argv) {
}
if (!(show | set | systohc | hctosys | systz | adjust | getepoch
- | setepoch))
+ | setepoch | predict))
show = 1; /* default to show */
@@ -1653,7 +1672,7 @@ main(int argc, char **argv) {
if (debug)
out_version();
- if (!systz) {
+ if (!systz && !predict) {
determine_clock_access_method(directisa);
if (!ur) {
fprintf(stderr,
@@ -1670,7 +1689,7 @@ main(int argc, char **argv) {
rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
hctosys, systohc, systz, startup_time, utc,
- local_opt, testing);
+ local_opt, testing, predict);
hwclock_exit(rc);
return rc; /* Not reached */
}
diff --git a/include/Makefile.am b/include/Makefile.am
index 525e3d2e..067523d7 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -12,6 +12,7 @@ dist_noinst_HEADERS = \
linux_reboot.h \
linux_version.h \
md5.h \
+ mbsalign.h \
nls.h \
pathnames.h \
setproctitle.h \
@@ -20,4 +21,7 @@ dist_noinst_HEADERS = \
wholedisk.h \
widechar.h \
crc32.h \
- xstrncpy.h
+ mangle.h \
+ strtosize.h \
+ xstrncpy.h \
+ writeall.h
diff --git a/include/blkdev.h b/include/blkdev.h
index 56a9c1f4..34e4e924 100644
--- a/include/blkdev.h
+++ b/include/blkdev.h
@@ -8,9 +8,6 @@
#define DEFAULT_SECTOR_SIZE 512
-/* open() retries when errno is ENOMEDIUM */
-#define CRDOM_NOMEDIUM_RETRIES 5
-
#if !defined(BLKROSET) && defined(__linux__)
#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
@@ -34,7 +31,11 @@
#define BLKBSZSET _IOW(0x12,113,size_t)
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif /* BLKROSET */
+#endif /* BLKROSET && __linux__ */
+
+#ifdef APPLE_DARWIN
+#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif
/* block device topology ioctls, introduced in 2.6.32 */
#ifndef BLKIOMIN
diff --git a/include/c.h b/include/c.h
index 413366b2..577b8a80 100644
--- a/include/c.h
+++ b/include/c.h
@@ -46,4 +46,20 @@
# define FALSE 0
#endif
+#ifndef min
+# define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+#endif
+
+#ifndef max
+# define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+#endif
+
#endif /* UTIL_LINUX_C_H */
diff --git a/include/fsprobe.h b/include/fsprobe.h
index 307eb64a..9e2bf50f 100644
--- a/include/fsprobe.h
+++ b/include/fsprobe.h
@@ -17,6 +17,7 @@ extern char *fsprobe_get_devname_by_spec(const char *spec);
extern char *fsprobe_get_label_by_devname(const char *devname);
extern char *fsprobe_get_uuid_by_devname(const char *devname);
extern char *fsprobe_get_fstype_by_devname(const char *devname);
+extern char *fsprobe_get_fstype_by_devname_ambi(const char *devname, int *ambi);
extern int fsprobe_known_fstype(const char *fstype);
diff --git a/include/mangle.h b/include/mangle.h
new file mode 100644
index 00000000..8ce38752
--- /dev/null
+++ b/include/mangle.h
@@ -0,0 +1,14 @@
+#ifndef UTIL_LINUX_MANGLE_H
+#define UTIL_LINUX_MANGLE_H
+
+/*
+ * Functions for \oct encoding used in mtab/fstab/swaps/etc.
+ */
+
+extern char *mangle(const char *s);
+
+extern void unmangle_to_buffer(char *s, char *buf, size_t len);
+extern char *unmangle(char *s);
+
+#endif /* UTIL_LINUX_MANGLE_H */
+
diff --git a/include/mbsalign.h b/include/mbsalign.h
new file mode 100644
index 00000000..fd957b39
--- /dev/null
+++ b/include/mbsalign.h
@@ -0,0 +1,45 @@
+/* Align/Truncate a string in a given screen width
+ Copyright (C) 2009-2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+
+typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t;
+
+enum {
+ /* Use unibyte mode for invalid multibyte strings or
+ or when heap memory is exhausted. */
+ MBA_UNIBYTE_FALLBACK = 0x0001,
+
+#if 0 /* Other possible options. */
+ /* Skip invalid multibyte chars rather than failing */
+ MBA_IGNORE_INVALID = 0x0002,
+
+ /* Align multibyte strings using "figure space" (\u2007) */
+ MBA_USE_FIGURE_SPACE = 0x0004,
+
+ /* Don't add any padding */
+ MBA_TRUNCATE_ONLY = 0x0008,
+
+ /* Don't truncate */
+ MBA_PAD_ONLY = 0x0010,
+#endif
+};
+
+extern size_t mbs_truncate(char *str, size_t *width);
+
+extern size_t mbsalign (const char *src, char *dest,
+ size_t dest_size, size_t *width,
+ mbs_align_t align, int flags);
diff --git a/include/pathnames.h b/include/pathnames.h
index 9c4eb009..7d57c528 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -12,6 +12,10 @@
# error "we need an ANSI compiler"
#endif
+/* used by kernel in /proc (e.g. /proc/swaps) for deleted files */
+#define PATH_DELETED_SUFFIX "\\040(deleted)"
+#define PATH_DELETED_SUFFIX_SZ (sizeof(PATH_DELETED_SUFFIX) - 1)
+
/* DEFPATHs from <paths.h> don't include /usr/local */
#undef _PATH_DEFPATH
#define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin"
diff --git a/include/strtosize.h b/include/strtosize.h
new file mode 100644
index 00000000..c789df93
--- /dev/null
+++ b/include/strtosize.h
@@ -0,0 +1,8 @@
+#ifndef UTIL_LINUX_STRTOSIZE
+#define UTIL_LINUX_STRTOSIZE
+
+#include <inttypes.h>
+
+extern int strtosize(const char *str, uintmax_t *res);
+
+#endif /* UTIL_LINUX_STRING_TO_NUMBE */
diff --git a/include/swapheader.h b/include/swapheader.h
index 6ff5390f..42d521a4 100644
--- a/include/swapheader.h
+++ b/include/swapheader.h
@@ -10,13 +10,17 @@ struct swap_header_v1 {
unsigned int badpages[1];
};
+
+#define SWAP_UUID_LENGTH 16
+#define SWAP_LABEL_LENGTH 16
+
struct swap_header_v1_2 {
char bootbits[1024]; /* Space for disklabel etc. */
unsigned int version;
unsigned int last_page;
unsigned int nr_badpages;
- unsigned char uuid[16];
- char volume_name[16];
+ unsigned char uuid[SWAP_UUID_LENGTH];
+ char volume_name[SWAP_LABEL_LENGTH];
unsigned int padding[117];
unsigned int badpages[1];
};
diff --git a/include/writeall.h b/include/writeall.h
new file mode 100644
index 00000000..a04496d8
--- /dev/null
+++ b/include/writeall.h
@@ -0,0 +1,25 @@
+#ifndef UTIL_LINUX_WRITEALL_H
+#define UTIL_LINUX_WRITEALL_H
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+static inline int write_all(int fd, const void *buf, size_t count)
+{
+ while(count) {
+ ssize_t tmp;
+
+ errno = 0;
+ tmp = write(fd, buf, count);
+ if (tmp > 0) {
+ count -= tmp;
+ if (count)
+ buf += tmp;
+ } else if (errno != EINTR && errno != EAGAIN)
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* UTIL_LINUX_WRITEALL_H */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5600d18c..0f008b30 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,11 +2,14 @@ include $(top_srcdir)/config/include-Makefile.am
AM_CPPFLAGS += -DTEST_PROGRAM
-noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk
+noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle \
+ test_strtosize
test_blkdev_SOURCES = blkdev.c
test_ismounted_SOURCES = ismounted.c
test_wholedisk_SOURCES = wholedisk.c
+test_mangle_SOURCES = mangle.c
+test_strtosize_SOURCES = strtosize.c
if LINUX
test_blkdev_SOURCES += linux_version.c
diff --git a/lib/blkdev.c b/lib/blkdev.c
index 1ca4548b..7d00324d 100644
--- a/lib/blkdev.c
+++ b/lib/blkdev.c
@@ -1,7 +1,24 @@
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
+#include <stdint.h>
+
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+
+#ifdef HAVE_SYS_DISKLABEL_H
+#include <sys/disklabel.h>
+#endif
+
+#ifdef HAVE_SYS_DISK_H
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h> /* for LIST_HEAD */
+#endif
+#include <sys/disk.h>
+#endif
#include "blkdev.h"
#include "linux_version.h"
@@ -19,14 +36,23 @@ blkdev_valid_offset (int fd, off_t offset) {
off_t
blkdev_find_size (int fd) {
- off_t high, low;
+ uintmax_t high, low = 0;
+
+ for (high = 1024; blkdev_valid_offset (fd, high); ) {
+ if (high == UINTMAX_MAX)
+ return -1;
- low = 0;
- for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2)
low = high;
+
+ if (high >= UINTMAX_MAX/2)
+ high = UINTMAX_MAX;
+ else
+ high *= 2;
+ }
+
while (low < high - 1)
{
- const off_t mid = (low + high) / 2;
+ uintmax_t mid = (low + high) / 2;
if (blkdev_valid_offset (fd, mid))
low = mid;
@@ -41,17 +67,26 @@ blkdev_find_size (int fd) {
int
blkdev_get_size(int fd, unsigned long long *bytes)
{
- /* TODO: use stat as well */
+#ifdef DKIOCGETBLOCKCOUNT
+ /* Apple Darwin */
+ if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
+ *bytes <<= 9;
+ return 0;
+ }
+#endif
#ifdef BLKGETSIZE64
+ {
#ifdef __linux__
- int ver = get_linux_version();
- /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
- if (ver >= KERNEL_VERSION (2,6,0) ||
- (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
+ int ver = get_linux_version();
+
+ /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
+ if (ver >= KERNEL_VERSION (2,6,0) ||
+ (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
#endif
- if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
- return 0;
+ if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
+ return 0;
+ }
#endif /* BLKGETSIZE64 */
#ifdef BLKGETSIZE
@@ -64,9 +99,67 @@ blkdev_get_size(int fd, unsigned long long *bytes)
}
}
- return -1;
#endif /* BLKGETSIZE */
+#ifdef DIOCGMEDIASIZE
+ /* FreeBSD */
+ if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
+ return 0
+#endif
+
+#ifdef FDGETPRM
+ {
+ struct floppy_struct this_floppy;
+
+ if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
+ *bytes = this_floppy.size << 9;
+ return 0;
+ }
+ }
+#endif /* FDGETPRM */
+
+#ifdef HAVE_SYS_DISKLABEL_H
+ {
+ /*
+ * This code works for FreeBSD 4.11 i386, except for the full device
+ * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
+ * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
+ * above however.
+ *
+ * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
+ * character) devices, so we need to check for S_ISCHR, too.
+ */
+ int part = -1;
+ struct disklabel lab;
+ struct partition *pp;
+ char ch;
+ struct stat st;
+
+ if ((fstat(fd, &st) >= 0) &&
+ (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
+ part = st.st_rdev & 7;
+
+ if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+ pp = &lab.d_partitions[part];
+ if (pp->p_size) {
+ *bytes = pp->p_size << 9;
+ return 0;
+ }
+ }
+ }
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+ {
+ struct stat st;
+
+ if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
+ *bytes = st.st_size;
+ return 0;
+ }
+ if (!S_ISBLK(st.st_mode))
+ return -1;
+ }
+
*bytes = blkdev_find_size(fd);
return 0;
}
diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index e54cf0c0..29b3f259 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -24,7 +24,6 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
-#include <string.h>
#include <errno.h>
#include <stdlib.h>
diff --git a/lib/fsprobe.c b/lib/fsprobe.c
index bc3c13c6..e92e03fc 100644
--- a/lib/fsprobe.c
+++ b/lib/fsprobe.c
@@ -20,34 +20,6 @@
static blkid_cache blcache;
-#ifdef HAVE_LIBBLKID_INTERNAL
-/* ask kernel developers why we need such ugly open() method... */
-static int
-open_device(const char *devname)
-{
- int retries = 0;
-
- do {
- int fd = open(devname, O_RDONLY);
- if (fd >= 0)
- return fd;
-#ifdef ENOMEDIUM
- /* ENOMEDIUM is Linux-only */
- if (errno != ENOMEDIUM)
- break;
-#else
- break;
-#endif
- if (retries >= CRDOM_NOMEDIUM_RETRIES)
- break;
- ++retries;
- sleep(3);
- } while(1);
-
- return -1;
-}
-#endif
-
/*
* Parses NAME=value, returns -1 on parse error, 0 success. The success is also
* when the 'spec' doesn't contain name=value pair (because the spec could be
@@ -122,14 +94,14 @@ fsprobe_exit(void)
* probing interface
*/
static char *
-fsprobe_get_value(const char *name, const char *devname)
+fsprobe_get_value(const char *name, const char *devname, int *ambi)
{
- int fd;
+ int fd, rc;
const char *data = NULL;
if (!devname || !name)
return NULL;
- fd = open_device(devname);
+ fd = open(devname, O_RDONLY);
if (fd < 0)
return NULL;
if (!blprobe)
@@ -144,10 +116,11 @@ fsprobe_get_value(const char *name, const char *devname)
blkid_probe_set_superblocks_flags(blprobe,
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE);
- if (blkid_do_safeprobe(blprobe))
- goto done;
- if (blkid_probe_lookup_value(blprobe, name, &data, NULL))
- goto done;
+ rc = blkid_do_safeprobe(blprobe);
+ if (ambi)
+ *ambi = rc == -2 ? 1 : 0; /* ambivalent probing result */
+ if (!rc)
+ blkid_probe_lookup_value(blprobe, name, &data, NULL);
done:
close(fd);
return data ? strdup((char *) data) : NULL;
@@ -156,19 +129,25 @@ done:
char *
fsprobe_get_label_by_devname(const char *devname)
{
- return fsprobe_get_value("LABEL", devname);
+ return fsprobe_get_value("LABEL", devname, NULL);
}
char *
fsprobe_get_uuid_by_devname(const char *devname)
{
- return fsprobe_get_value("UUID", devname);
+ return fsprobe_get_value("UUID", devname, NULL);
}
char *
fsprobe_get_fstype_by_devname(const char *devname)
{
- return fsprobe_get_value("TYPE", devname);
+ return fsprobe_get_value("TYPE", devname, NULL);
+}
+
+char *
+fsprobe_get_fstype_by_devname_ambi(const char *devname, int *ambi)
+{
+ return fsprobe_get_value("TYPE", devname, ambi);
}
char *
@@ -237,6 +216,14 @@ fsprobe_get_fstype_by_devname(const char *devname)
}
char *
+fsprobe_get_fstype_by_devname_ambi(const char *devname, int *ambi)
+{
+ if (ambi)
+ *ambi = 0;
+ return fsprobe_get_fstype_by_devname(devname);
+}
+
+char *
fsprobe_get_label_by_devname(const char *devname)
{
if (!blcache)
diff --git a/lib/mangle.c b/lib/mangle.c
new file mode 100644
index 00000000..766d479d
--- /dev/null
+++ b/lib/mangle.c
@@ -0,0 +1,116 @@
+/*
+ * Functions for \oct encoding used in mtab/fstab/swaps/etc.
+ *
+ * Based on code from mount(8).
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mangle.h"
+
+#define isoctal(a) (((a) & ~7) == '0')
+
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+char *mangle(const char *s)
+{
+ char *ss, *sp;
+ int n;
+
+ n = strlen(s);
+ ss = sp = malloc(4*n+1);
+ if (!sp)
+ return NULL;
+ while(1) {
+ for (n = 0; n < sizeof(need_escaping); n++) {
+ if (*s == need_escaping[n]) {
+ *sp++ = '\\';
+ *sp++ = '0' + ((*s & 0300) >> 6);
+ *sp++ = '0' + ((*s & 070) >> 3);
+ *sp++ = '0' + (*s & 07);
+ goto next;
+ }
+ }
+ *sp++ = *s;
+ if (*s == 0)
+ break;
+ next:
+ s++;
+ }
+ return ss;
+}
+
+void unmangle_to_buffer(char *s, char *buf, size_t len)
+{
+ size_t sz = 0;
+
+ while(*s && sz < len - 1) {
+ if (*s == '\\' && sz + 4 < len - 1 && isoctal(s[1]) &&
+ isoctal(s[2]) && isoctal(s[3])) {
+
+ *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
+ s += 4;
+ sz += 4;
+ } else {
+ *buf++ = *s++;
+ sz++;
+ }
+ }
+ *buf = '\0';
+}
+
+static inline char *skip_nonspaces(char *s)
+{
+ while (*s && !(*s == ' ' || *s == '\t'))
+ s++;
+ return s;
+}
+
+/*
+ * Returns mallocated buffer or NULL in case of error.
+ */
+char *unmangle(char *s)
+{
+ char *buf, *end;
+ size_t sz;
+
+ end = skip_nonspaces(s);
+ sz = end - s + 1;
+
+ buf = malloc(sz);
+ if (!buf)
+ return NULL;
+
+ unmangle_to_buffer(s, buf, sz);
+ return buf;
+}
+
+#ifdef TEST_PROGRAM
+#include <err.h>
+#include <errno.h>
+int main(int argc, char *argv[])
+{
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n",
+ program_invocation_short_name);
+ return EXIT_FAILURE;
+ }
+
+ if (!strcmp(argv[1], "--mangle"))
+ printf("mangled: '%s'\n", mangle(argv[2]));
+
+ else if (!strcmp(argv[1], "--unmangle")) {
+ char *x = unmangle(argv[2]);
+ if (x)
+ printf("unmangled: '%s'\n", x);
+ else
+ err(EXIT_FAILURE, "unmangle failed");
+ }
+
+ return EXIT_SUCCESS;
+}
+#endif /* TEST_PROGRAM */
diff --git a/lib/mbsalign.c b/lib/mbsalign.c
new file mode 100644
index 00000000..82ffc09c
--- /dev/null
+++ b/lib/mbsalign.c
@@ -0,0 +1,288 @@
+/* Align/Truncate a string in a given screen width
+ Copyright (C) 2009-2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Pádraig Brady. */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <limits.h>
+
+#include "c.h"
+#include "mbsalign.h"
+#include "widechar.h"
+
+
+#ifdef HAVE_WIDECHAR
+/* Replace non printable chars.
+ Note \t and \n etc. are non printable.
+ Return 1 if replacement made, 0 otherwise. */
+
+static bool
+wc_ensure_printable (wchar_t *wchars)
+{
+ bool replaced = false;
+ wchar_t *wc = wchars;
+ while (*wc)
+ {
+ if (!iswprint ((wint_t) *wc))
+ {
+ *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
+ replaced = true;
+ }
+ wc++;
+ }
+ return replaced;
+}
+
+/* Truncate wchar string to width cells.
+ * Returns number of cells used. */
+
+static size_t
+wc_truncate (wchar_t *wc, size_t width)
+{
+ size_t cells = 0;
+ int next_cells = 0;
+
+ while (*wc)
+ {
+ next_cells = wcwidth (*wc);
+ if (next_cells == -1) /* non printable */
+ {
+ *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
+ next_cells = 1;
+ }
+ if (cells + next_cells > width)
+ break;
+ cells += next_cells;
+ wc++;
+ }
+ *wc = L'\0';
+ return cells;
+}
+
+/* FIXME: move this function to gnulib as it's missing on:
+ OpenBSD 3.8, IRIX 5.3, Solaris 2.5.1, mingw, BeOS */
+
+static int
+rpl_wcswidth (const wchar_t *s, size_t n)
+{
+ int ret = 0;
+
+ while (n-- > 0 && *s != L'\0')
+ {
+ int nwidth = wcwidth (*s++);
+ if (nwidth == -1) /* non printable */
+ return -1;
+ if (ret > (INT_MAX - nwidth)) /* overflow */
+ return -1;
+ ret += nwidth;
+ }
+
+ return ret;
+}
+#endif
+
+/* Truncate multi-byte string to @width and returns number of
+ * bytes of the new string @str, and in @width returns number
+ * of cells.
+ */
+size_t
+mbs_truncate(char *str, size_t *width)
+{
+ size_t bytes = strlen(str);
+#ifdef HAVE_WIDECHAR
+ size_t sz = mbstowcs(NULL, str, 0);
+ wchar_t *wcs = NULL;
+
+ if (sz == (size_t) -1)
+ goto done;
+
+ wcs = malloc((sz + 1) * sizeof(wchar_t));
+ if (!wcs)
+ goto done;
+
+ if (!mbstowcs(wcs, str, sz))
+ goto done;
+ *width = wc_truncate(wcs, *width);
+ bytes = wcstombs(str, wcs, bytes);
+done:
+ free(wcs);
+#else
+ if (*width < bytes)
+ bytes = *width;
+#endif
+ if (bytes >= 0)
+ str[bytes] = '\0';
+ return bytes;
+}
+
+/* Write N_SPACES space characters to DEST while ensuring
+ nothing is written beyond DEST_END. A terminating NUL
+ is always added to DEST.
+ A pointer to the terminating NUL is returned. */
+
+static char*
+mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
+{
+ /* FIXME: Should we pad with "figure space" (\u2007)
+ if non ascii data present? */
+ while (n_spaces-- && (dest < dest_end))
+ *dest++ = ' ';
+ *dest = '\0';
+ return dest;
+}
+
+/* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte
+ characters; write the result into the DEST_SIZE-byte buffer, DEST.
+ ALIGNMENT specifies whether to left- or right-justify or to center.
+ If SRC requires more than *WIDTH columns, truncate it to fit.
+ When centering, the number of trailing spaces may be one less than the
+ number of leading spaces. The FLAGS parameter is unused at present.
+ Return the length in bytes required for the final result, not counting
+ the trailing NUL. A return value of DEST_SIZE or larger means there
+ wasn't enough space. DEST will be NUL terminated in any case.
+ Return (size_t) -1 upon error (invalid multi-byte sequence in SRC,
+ or malloc failure), unless MBA_UNIBYTE_FALLBACK is specified.
+ Update *WIDTH to indicate how many columns were used before padding. */
+
+size_t
+mbsalign (const char *src, char *dest, size_t dest_size,
+ size_t *width, mbs_align_t align, int flags)
+{
+ size_t ret = -1;
+ size_t src_size = strlen (src) + 1;
+ char *newstr = NULL;
+ wchar_t *str_wc = NULL;
+ const char *str_to_print = src;
+ size_t n_cols = src_size - 1;
+ size_t n_used_bytes = n_cols; /* Not including NUL */
+ size_t n_spaces = 0;
+ bool conversion = false;
+ bool wc_enabled = false;
+
+#ifdef HAVE_WIDECHAR
+ /* In multi-byte locales convert to wide characters
+ to allow easy truncation. Also determine number
+ of screen columns used. */
+ if (MB_CUR_MAX > 1)
+ {
+ size_t src_chars = mbstowcs (NULL, src, 0);
+ if (src_chars == (size_t) -1)
+ {
+ if (flags & MBA_UNIBYTE_FALLBACK)
+ goto mbsalign_unibyte;
+ else
+ goto mbsalign_cleanup;
+ }
+ src_chars += 1; /* make space for NUL */
+ str_wc = malloc (src_chars * sizeof (wchar_t));
+ if (str_wc == NULL)
+ {
+ if (flags & MBA_UNIBYTE_FALLBACK)
+ goto mbsalign_unibyte;
+ else
+ goto mbsalign_cleanup;
+ }
+ if (mbstowcs (str_wc, src, src_chars) != 0)
+ {
+ str_wc[src_chars - 1] = L'\0';
+ wc_enabled = true;
+ conversion = wc_ensure_printable (str_wc);
+ n_cols = rpl_wcswidth (str_wc, src_chars);
+ }
+ }
+
+ /* If we transformed or need to truncate the source string
+ then create a modified copy of it. */
+ if (wc_enabled && (conversion || (n_cols > *width)))
+ {
+ if (conversion)
+ {
+ /* May have increased the size by converting
+ \t to \uFFFD for example. */
+ src_size = wcstombs(NULL, str_wc, 0) + 1;
+ }
+ newstr = malloc (src_size);
+ if (newstr == NULL)
+ {
+ if (flags & MBA_UNIBYTE_FALLBACK)
+ goto mbsalign_unibyte;
+ else
+ goto mbsalign_cleanup;
+ }
+ str_to_print = newstr;
+ n_cols = wc_truncate (str_wc, *width);
+ n_used_bytes = wcstombs (newstr, str_wc, src_size);
+ }
+#endif
+
+mbsalign_unibyte:
+
+ if (n_cols > *width) /* Unibyte truncation required. */
+ {
+ n_cols = *width;
+ n_used_bytes = n_cols;
+ }
+
+ if (*width > n_cols) /* Padding required. */
+ n_spaces = *width - n_cols;
+
+ /* indicate to caller how many cells needed (not including padding). */
+ *width = n_cols;
+
+ /* indicate to caller how many bytes needed (not including NUL). */
+ ret = n_used_bytes + (n_spaces * 1);
+
+ /* Write as much NUL terminated output to DEST as possible. */
+ if (dest_size != 0)
+ {
+ char *dest_end = dest + dest_size - 1;
+ size_t start_spaces = n_spaces / 2 + n_spaces % 2;
+ size_t end_spaces = n_spaces / 2;
+
+ switch (align)
+ {
+ case MBS_ALIGN_CENTER:
+ start_spaces = n_spaces / 2 + n_spaces % 2;
+ end_spaces = n_spaces / 2;
+ break;
+ case MBS_ALIGN_LEFT:
+ start_spaces = 0;
+ end_spaces = n_spaces;
+ break;
+ case MBS_ALIGN_RIGHT:
+ start_spaces = n_spaces;
+ end_spaces = 0;
+ break;
+ }
+
+ dest = mbs_align_pad (dest, dest_end, start_spaces);
+ size_t space_left = dest_end - dest;
+ dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left));
+ mbs_align_pad (dest, dest_end, end_spaces);
+ }
+
+mbsalign_cleanup:
+
+ free (str_wc);
+ free (newstr);
+
+ return ret;
+}
diff --git a/lib/strtosize.c b/lib/strtosize.c
new file mode 100644
index 00000000..068c5429
--- /dev/null
+++ b/lib/strtosize.c
@@ -0,0 +1,148 @@
+/*
+ * strtosize() - convert string to size (uintmax_t).
+ *
+ * Supported suffixes:
+ *
+ * XiB or X for 2^N
+ * where X = {K,M,G,T,P,E,Y,Z}
+ * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only)
+ * for example:
+ * 10KiB = 10240
+ * 10K = 10240
+ *
+ * XB for 10^N
+ * where X = {K,M,G,T,P,E,Y,Z}
+ * for example:
+ * 10KB = 10000
+ *
+ * Note that the function does not accept numbers with '-' (negative sign)
+ * prefix.
+ *
+ * Returns 0 on success, -1 in case of error, -2 in case of overflow.
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <errno.h>
+
+static int do_scale_by_power (uintmax_t *x, int base, int power)
+{
+ while (power--) {
+ if (UINTMAX_MAX / base < *x)
+ return -2;
+ *x *= base;
+ }
+ return 0;
+}
+
+int strtosize(const char *str, uintmax_t *res)
+{
+ char *p;
+ uintmax_t x;
+ int base = 1024, rc = 0;
+
+ *res = 0;
+
+ if (!str || !*str)
+ goto err;
+
+ /* Only positive numbers are acceptable
+ *
+ * Note that this check is not perfect, it would be better to
+ * use lconv->negative_sign. But coreutils use the same solution,
+ * so it's probably good enough...
+ */
+ p = (char *) str;
+ while (isspace((unsigned char) *p))
+ p++;
+ if (*p == '-')
+ goto err;
+ p = NULL;
+
+ errno = 0;
+ x = strtoumax(str, &p, 0);
+
+ if (p == str ||
+ (errno != 0 && (x == UINTMAX_MAX || x == 0)))
+ goto err;
+
+ if (!p || !*p)
+ goto done; /* without suffix */
+
+ /*
+ * Check size suffixes
+ */
+ if (*(p + 1) == 'i' && *(p + 2) == 'B' && !*(p + 3))
+ base = 1024; /* XiB, 2^N */
+ else if (*(p + 1) == 'B' && !*(p + 2))
+ base = 1000; /* XB, 10^N */
+ else if (*(p + 1))
+ goto err; /* unexpected suffix */
+
+ switch(*p) {
+ case 'K':
+ case 'k':
+ rc = do_scale_by_power(&x, base, 1);
+ break;
+ case 'M':
+ case 'm':
+ rc = do_scale_by_power(&x, base, 2);
+ break;
+ case 'G':
+ case 'g':
+ rc = do_scale_by_power(&x, base, 3);
+ break;
+ case 'T':
+ case 't':
+ rc = do_scale_by_power(&x, base, 4);
+ break;
+ case 'P':
+ case 'p':
+ rc = do_scale_by_power(&x, base, 5);
+ break;
+ case 'E':
+ case 'e':
+ rc = do_scale_by_power(&x, base, 6);
+ break;
+ case 'Z':
+ rc = do_scale_by_power(&x, base, 7);
+ break;
+ case 'Y':
+ rc = do_scale_by_power(&x, base, 8);
+ break;
+ default:
+ goto err;
+ }
+
+done:
+ *res = x;
+ return rc;
+err:
+ return -1;
+}
+
+#ifdef TEST_PROGRAM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+
+int main(int argc, char *argv[])
+{
+ uintmax_t size = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <number>[suffix]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (strtosize(argv[1], &size))
+ errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]);
+
+ printf("%25s : %20ju\n", argv[1], size);
+ return EXIT_FAILURE;
+}
+#endif /* TEST_PROGRAM */
+
diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am
index 6176ab7d..ca272560 100644
--- a/misc-utils/Makefile.am
+++ b/misc-utils/Makefile.am
@@ -11,6 +11,7 @@ usrbin_exec_PROGRAMS = cal ddate logger look mcookie \
EXTRA_DIST += README.cal README.ddate README.namei README.namei2
mcookie_SOURCES = mcookie.c ../lib/md5.c
+script_LDADD =
usrbin_exec_SCRIPTS = chkdupexe
@@ -35,11 +36,12 @@ endif
if BUILD_LIBBLKID
sbin_PROGRAMS += blkid findfs wipefs
dist_man_MANS += blkid.8 findfs.8 wipefs.8
-blkid_SOURCES = blkid.c $(top_srcdir)/lib/ismounted.c
+blkid_SOURCES = blkid.c $(top_srcdir)/lib/ismounted.c ../lib/strtosize.c
blkid_LDADD = $(ul_libblkid_la)
blkid_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir)
findfs_LDADD = $(ul_libblkid_la)
findfs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir)
+wipefs_SOURCES = wipefs.c ../lib/strtosize.c
wipefs_LDADD = $(ul_libblkid_la)
wipefs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir)
if HAVE_STATIC_BLKID
@@ -51,6 +53,7 @@ blkid_static_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir)
endif
endif
+cal_SOURCES = cal.c $(top_srcdir)/lib/mbsalign.c
if HAVE_TINFO
cal_LDADD = -ltinfo @NCURSES_LIBS@
else
@@ -64,7 +67,11 @@ endif
endif
if HAVE_UTIL
-script_LDADD = -lutil
+script_LDADD += -lutil
+endif
+
+if HAVE_UTEMPTER
+script_LDADD += -lutempter
endif
if HAVE_NCURSES
diff --git a/misc-utils/blkid.8 b/misc-utils/blkid.8
index 9419da0f..d42074f0 100644
--- a/misc-utils/blkid.8
+++ b/misc-utils/blkid.8
@@ -28,12 +28,13 @@ blkid \- command\-line utility to locate/print block device attributes
.IR tag ]
.RB [ \-t
.IR NAME=value ]
-.I device
[\fIdevice\fR ...]
.in -6
.B blkid
.RB -p
+.RB [ \-s
+.IR tag ]
.RB [ \-O
.IR offset ]
.RB [ \-S
@@ -43,10 +44,24 @@ blkid \- command\-line utility to locate/print block device attributes
.RB [ \-s
.IR tag ]
.in +9
+.RB [ \-n
+.IR list ]
.RB [ \-u
.IR list ]
.I device
[\fIdevice\fR ...]
+.in -9
+
+.B blkid
+.RB -i
+.RB [ \-s
+.IR tag ]
+.RB [ \-o
+.IR format ]
+.RB [ \-s
+.IR tag ]
+.I device
+[\fIdevice\fR ...]
.SH DESCRIPTION
The
@@ -62,6 +77,9 @@ has two main forms of operation: either searching for a device with a
specific NAME=value pair, or displaying NAME=value pairs for one or
more devices.
.SH OPTIONS
+The \fIsize\fR and \fIoffset\fR arguments may be followed by binary (2^N)
+suffixes KiB, MiB, GiB, TiB, PiB and EiB (the "iB" is optional, e.g. "K" has the
+same meaning as "KiB") or decimal (10^N) suffixes KB, MB, GB, PB and EB.
.TP
.BI \-c " cachefile"
Read from
@@ -79,6 +97,10 @@ devices which no longer exist.
.B \-h
Display a usage message and exit.
.TP
+.B \-i
+Display I/O Limits (aka I/O topology) information. The 'export' output format is
+automatically enabled. This option could be used together with \fB-p\fR option.
+.TP
.B \-l
Look up one device that matches the search parameter specified using
the
@@ -104,23 +126,21 @@ from e2fsprogs use the \fB-L\fR option as a
synonym to the \fB-o list\fR option. For better portability use "-l -o device
-t LABEL=<label>" and "-o list" in your scripts rather than -L option.
.TP
-.B \-u " list "
-Restrict probing functions to defined (comma separated) list of "usage" types.
-Supported usage types are: filesystem, raid, crypto and other. The list can be
-prefixed with "no" to specify the usage types which should be ignored. For example:
+.B \-n " list "
+Restrict probing functions to defined (comma separated) list of superblock types (names).
+The list can be prefixed with "no" to specify the types which should be ignored.
+For example:
.sp
- blkid -p -u filesystem,other /dev/sda1
+ blkid -p -n vfat,ext3,ext4 /dev/sda1
.sp
-probes for all filesystems and others (e.g. swap) formats, and
+probes for vfat, ext3 and ext4 filesystems, and
.sp
- blkid -p -u noraid /dev/sda1
+ blkid -p -u nominix /dev/sda1
.sp
-probes for all supported formats exclude RAIDs. This option is useful with
+probes for all supported formats exclude minix filesystem. This option is
+useful with
\fB-p\fR only.
.TP
-.B \-U " uuid "
-Look up one device that uses the uuid. For more details see the \fB-L\fR option.
-.TP
.BI \-o " format"
Display
.BR blkid 's
@@ -137,21 +157,26 @@ print the value of the tags
.TP
.B list
print the devices in a user-friendly format, this output format is unsupported
-for low-level probing (\fB-p\fR)
+for low-level probing (\fB-p\fR or \fB-i\fR)
.TP
.B device
print the device name only, this output format is always enabled for \fB-L\fR
and \fB-U\fR options
.TP
.B udev
-vol_id compatible mode; usable in udev rules
+print key="value" pairs for easy import into the udev environment
+.TP
+.B export
+print key=value pairs for easy import into the environment. This output format
+is automatically enabled when I/O Limits (\fB-i\fR option) are requested.
.RE
.TP
-.BI \-O " bytes"
-Probe at the given offset (only useful with \fB-p\fR).
+.BI \-O " offset"
+Probe at the given offset (only useful with \fB-p\fR). This option could be
+used together with \fB-i\fR option.
.TP
.BI \-p
-Switch to low-level probing mode (bypass cache)
+Switch to low-level superblock probing mode (bypass cache).
.TP
.BI \-s " tag"
For each (specified) device, show only the tags that match
@@ -164,7 +189,7 @@ In order to just refresh the cache without showing any tokens, use
.B "-s none"
with no other options.
.TP
-.BI \-S " bytes"
+.BI \-S " size"
Overwrite device/file size (only useful with \fB-p\fR).
.TP
.BI \-t " NAME" = "value"
@@ -183,6 +208,23 @@ and
If there are no devices specified on the command line, all block devices
will be searched; otherwise only the specified devices are searched.
.TP
+.B \-u " list "
+Restrict probing functions to defined (comma separated) list of "usage" types.
+Supported usage types are: filesystem, raid, crypto and other. The list can be
+prefixed with "no" to specify the usage types which should be ignored. For example:
+.sp
+ blkid -p -u filesystem,other /dev/sda1
+.sp
+probes for all filesystems and others (e.g. swap) formats, and
+.sp
+ blkid -p -u noraid /dev/sda1
+.sp
+probes for all supported formats exclude RAIDs. This option is useful with
+\fB-p\fR only.
+.TP
+.B \-U " uuid "
+Look up one device that uses the uuid. For more details see the \fB-L\fR option.
+.TP
.B \-v
Display version number and exit.
.TP
diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c
index 56b25b8b..48af7674 100644
--- a/misc-utils/blkid.c
+++ b/misc-utils/blkid.c
@@ -16,12 +16,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#ifdef HAVE_TERMIOS_H
#include <termios.h>
-#endif
-#ifdef HAVE_TERMIO_H
-#include <termio.h>
-#endif
+#include <errno.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -33,14 +29,19 @@ extern char *optarg;
extern int optind;
#endif
-#define OUTPUT_VALUE_ONLY 0x0001
-#define OUTPUT_DEVICE_ONLY 0x0002
-#define OUTPUT_PRETTY_LIST 0x0004
-#define OUTPUT_UDEV_LIST 0x0008
+#define OUTPUT_VALUE_ONLY (1 << 1)
+#define OUTPUT_DEVICE_ONLY (1 << 2)
+#define OUTPUT_PRETTY_LIST (1 << 3)
+#define OUTPUT_UDEV_LIST (1 << 4)
+#define OUTPUT_EXPORT_LIST (1 << 5)
+
+#define LOWPROBE_TOPOLOGY (1 << 1)
+#define LOWPROBE_SUPERBLOCKS (1 << 2)
#include <blkid.h>
#include "ismounted.h"
+#include "strtosize.h"
const char *progname = "blkid";
@@ -60,13 +61,15 @@ static void usage(int error)
" %1$s -L <label> | -U <uuid>\n\n"
" %1$s [-c <file>] [-ghlLv] [-o format] [-s <tag>] \n"
" [-t <token>] [-w <file>] [dev ...]\n\n"
- " %1$s -p [-O <offset>] [-S <size>] [-o format] <dev> [dev ...]\n\n"
+ " %1$s -p [-s <tag>] [-O <offset>] [-S <size>] \n"
+ " [-o format] <dev> [dev ...]\n\n"
+ " %1$s -i [-s <tag>] [-o format] <dev> [dev ...]\n\n"
"Options:\n"
" -c <file> cache file (default: /etc/blkid.tab, /dev/null = none)\n"
" -h print this usage message and exit\n"
" -g garbage collect the blkid cache\n"
" -o <format> output format; can be one of:\n"
- " value, device, list, udev or full; (default: full)\n"
+ " value, device, list, udev, export or full; (default: full)\n"
" -s <tag> show specified tag(s) (default show all tags)\n"
" -t <token> find device with a specific token (NAME=value pair)\n"
" -l lookup the the first device with arguments specified by -t\n"
@@ -76,10 +79,12 @@ static void usage(int error)
" -w <file> write cache to different file (/dev/null = no write)\n"
" <dev> specify device(s) to probe (default: all devices)\n\n"
"Low-level probing options:\n"
- " -p switch to low-level mode (bypass cache)\n"
- " -S <bytes> overwrite device size\n"
- " -O <bytes> probe at the given offset\n"
+ " -p low-level superblocks probing (bypass cache)\n"
+ " -i gather information about I/O limits\n"
+ " -S <size> overwrite device size\n"
+ " -O <offset> probe at the given offset\n"
" -u <list> filter by \"usage\" (e.g. -u filesystem,raid)\n"
+ " -n <list> filter by filesystem type (e.g. -n vfat,ext3)\n"
"\n",
progname);
@@ -239,6 +244,7 @@ static void pretty_print_dev(blkid_dev dev)
static void print_udev_format(const char *name, const char *value, size_t sz)
{
char enc[265], safe[256];
+ size_t namelen = strlen(name);
*safe = *enc = '\0';
@@ -256,11 +262,26 @@ static void print_udev_format(const char *name, const char *value, size_t sz)
blkid_encode_string(value, enc, sizeof(enc));
printf("ID_FS_%s_ENC=%s\n", name, enc);
- } else if (!strcmp(name, "PTTYPE"))
+ } else if (!strcmp(name, "PTTYPE")) {
printf("ID_PART_TABLE_TYPE=%s\n", value);
- /* TODO: ID_PART_ENTRY_{UUID,NAME,FLAG} */
+ } else if (!strcmp(name, "PART_ENTRY_NAME") ||
+ !strcmp(name, "PART_ENTRY_TYPE")) {
+
+ blkid_safe_string(value, safe, sizeof(safe));
+ printf("ID_%s=%s\n", name, safe);
+
+ blkid_encode_string(value, enc, sizeof(enc));
+ printf("ID_%s_ENC=%s\n", name, enc);
+
+ } else if (!strncmp(name, "PART_ENTRY_", 11))
+ printf("ID_%s=%s\n", name, value);
+ else if (namelen >= 15 && (
+ !strcmp(name + (namelen - 12), "_SECTOR_SIZE") ||
+ !strcmp(name + (namelen - 8), "_IO_SIZE") ||
+ !strcmp(name, "ALIGNMENT_OFFSET")))
+ printf("ID_IOLIMIT_%s=%s\n", name, value);
else
printf("ID_FS_%s=%s\n", name, value);
}
@@ -285,6 +306,12 @@ static void print_value(int output, int num, const char *devname,
} else if (output & OUTPUT_UDEV_LIST) {
print_udev_format(name, value, valsz);
+ } else if (output & OUTPUT_EXPORT_LIST) {
+ fputs(name, stdout);
+ fputs("=", stdout);
+ safe_print(value, valsz);
+ fputs("\n", stdout);
+
} else {
if (num == 1 && devname)
printf("%s: ", devname);
@@ -300,6 +327,7 @@ static void print_tags(blkid_dev dev, char *show[], int output)
blkid_tag_iterate iter;
const char *type, *value, *devname;
int num = 1;
+ static int first = 1;
if (!dev)
return;
@@ -320,12 +348,22 @@ static void print_tags(blkid_dev dev, char *show[], int output)
while (blkid_tag_next(iter, &type, &value) == 0) {
if (show[0] && !has_item(show, type))
continue;
+
+ if (num == 1 && !first &&
+ (output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)))
+ /* add extra line between output from more devices */
+ fputc('\n', stdout);
+
print_value(output, num++, devname, value, type, strlen(value));
}
blkid_tag_iterate_end(iter);
- if (num > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST)))
- printf("\n");
+ if (num > 1) {
+ if (!(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST |
+ OUTPUT_EXPORT_LIST)))
+ printf("\n");
+ first = 0;
+ }
}
@@ -406,8 +444,54 @@ done:
return rc;
}
-static int lowprobe_device(blkid_probe pr, const char *devname, char *show[],
- int output, blkid_loff_t offset, blkid_loff_t size)
+static int lowprobe_superblocks(blkid_probe pr)
+{
+ struct stat st;
+ int rc;
+
+ if (fstat(blkid_probe_get_fd(pr), &st))
+ return -1;
+
+ blkid_probe_enable_partitions(pr, 1);
+ blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
+
+ if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440) {
+ /*
+ * check if the small disk is partitioned, if yes then
+ * don't probe for filesystems.
+ */
+ blkid_probe_enable_superblocks(pr, 0);
+
+ rc = blkid_do_fullprobe(pr);
+ if (rc < 0)
+ return rc; /* -1 = error, 1 = nothing, 0 = succes */
+
+ if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0)
+ return 0; /* partition table detected */
+
+ /* small whole-disk is unpartitioned, probe for filesystems only */
+ blkid_probe_enable_partitions(pr, 0);
+ }
+
+ blkid_probe_enable_superblocks(pr, 1);
+
+ return blkid_do_safeprobe(pr);
+}
+
+static int lowprobe_topology(blkid_probe pr)
+{
+ /* enable topology probing only */
+ blkid_probe_enable_topology(pr, 1);
+
+ blkid_probe_enable_superblocks(pr, 0);
+ blkid_probe_enable_partitions(pr, 0);
+
+ return blkid_do_fullprobe(pr);
+}
+
+static int lowprobe_device(blkid_probe pr, const char *devname,
+ int chain, char *show[], int output,
+ blkid_loff_t offset, blkid_loff_t size)
{
const char *data;
const char *name;
@@ -415,46 +499,29 @@ static int lowprobe_device(blkid_probe pr, const char *devname, char *show[],
size_t len;
int fd;
int rc = 0;
- struct stat st;
+ static int first = 1;
fd = open(devname, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
+ fprintf(stderr, "error: %s: %s\n", devname, strerror(errno));
return 2;
-
+ }
if (blkid_probe_set_device(pr, fd, offset, size))
goto done;
- if (fstat(fd, &st))
- goto done;
- /*
- * partitions probing
- */
- blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */
-
- blkid_probe_enable_partitions(pr, 1);
- rc = blkid_do_fullprobe(pr);
- blkid_probe_enable_partitions(pr, 0);
-
+ if (chain & LOWPROBE_TOPOLOGY)
+ rc = lowprobe_topology(pr);
+ if (rc >= 0 && (chain & LOWPROBE_SUPERBLOCKS))
+ rc = lowprobe_superblocks(pr);
if (rc < 0)
- goto done; /* -1 = error, 1 = nothing, 0 = succes */
-
- /*
- * Don't probe for FS/RAIDs on small devices
- */
- if (rc || S_ISCHR(st.st_mode) ||
- blkid_probe_get_size(pr) > 1024 * 1440) {
- /*
- * filesystems/RAIDs probing
- */
- blkid_probe_enable_superblocks(pr, 1);
-
- rc = blkid_do_safeprobe(pr);
- if (rc < 0)
- goto done;
- }
+ goto done;
nvals = blkid_probe_numof_values(pr);
+ if (nvals && !first && output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST))
+ /* add extra line between output from devices */
+ fputc('\n', stdout);
+
if (output & OUTPUT_DEVICE_ONLY) {
printf("%s\n", devname);
goto done;
@@ -469,7 +536,10 @@ static int lowprobe_device(blkid_probe pr, const char *devname, char *show[],
print_value(output, num++, devname, (char *) data, name, len);
}
- if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST)))
+ if (first)
+ first = 0;
+ if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY |
+ OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)))
printf("\n");
done:
if (rc == -2) {
@@ -490,32 +560,89 @@ done:
static int list_to_usage(const char *list, int *flag)
{
int mask = 0;
- const char *word, *p = list;
+ const char *word = NULL, *p = list;
if (p && strncmp(p, "no", 2) == 0) {
*flag = BLKID_FLTR_NOTIN;
p += 2;
}
-
- for (word = p; p && *p; p++) {
- if (*p == ',' || *(p + 1) == '\0') {
- if (!strncmp(word, "filesystem", 10))
- mask |= BLKID_USAGE_FILESYSTEM;
- else if (!strncmp(word, "raid", 4))
- mask |= BLKID_USAGE_RAID;
- else if (!strncmp(word, "crypto", 6))
- mask |= BLKID_USAGE_CRYPTO;
- else if (!strncmp(word, "other", 5))
- mask |= BLKID_USAGE_OTHER;
- else {
- fprintf(stderr, "unknown usage keyword '%*s'\n",
- (int) (p - word), word);
- exit(4);
- }
- word = p + 1;
- }
+ if (!p || !*p)
+ goto err;
+ while(p) {
+ word = p;
+ p = strchr(p, ',');
+ if (p)
+ p++;
+ if (!strncmp(word, "filesystem", 10))
+ mask |= BLKID_USAGE_FILESYSTEM;
+ else if (!strncmp(word, "raid", 4))
+ mask |= BLKID_USAGE_RAID;
+ else if (!strncmp(word, "crypto", 6))
+ mask |= BLKID_USAGE_CRYPTO;
+ else if (!strncmp(word, "other", 5))
+ mask |= BLKID_USAGE_OTHER;
+ else
+ goto err;
}
return mask;
+err:
+ *flag = 0;
+ fprintf(stderr, "unknown kerword in -u <list> argument: '%s'\n",
+ word ? word : list);
+ exit(4);
+}
+
+/* converts comma separated list to types[] */
+static char **list_to_types(const char *list, int *flag)
+{
+ int i;
+ const char *p = list;
+ char **res;
+
+ if (p && strncmp(p, "no", 2) == 0) {
+ *flag = BLKID_FLTR_NOTIN;
+ p += 2;
+ }
+ if (!p || !*p) {
+ fprintf(stderr, "error: -u <list> argument is empty\n");
+ goto err;
+ }
+ for (i = 1; p && (p = strchr(p, ',')); i++, p++);
+
+ res = calloc(i + 1, sizeof(char *));
+ if (!res)
+ goto err_mem;
+ p = *flag & BLKID_FLTR_NOTIN ? list + 2 : list;
+ i = 0;
+
+ while(p) {
+ const char *word = p;
+ p = strchr(p, ',');
+ res[i] = p ? strndup(word, p - word) : strdup(word);
+ if (!res[i++])
+ goto err_mem;
+ if (p)
+ p++;
+ }
+ res[i] = NULL;
+ return res;
+err_mem:
+ fprintf(stderr, "out of memory\n");
+err:
+ *flag = 0;
+ free(res);
+ exit(4);
+}
+
+static void free_types_list(char *list[])
+{
+ char **n;
+
+ if (!list)
+ return;
+ for (n = list; *n; n++)
+ free(*n);
+ free(list);
}
int main(int argc, char **argv)
@@ -527,6 +654,7 @@ int main(int argc, char **argv)
char *read = NULL;
char *write = NULL;
int fltr_usage = 0;
+ char **fltr_type = NULL;
int fltr_flag = BLKID_FLTR_ONLYIN;
unsigned int numdev = 0, numtag = 0;
int version = 0;
@@ -535,11 +663,11 @@ int main(int argc, char **argv)
int output_format = 0;
int lookup = 0, gc = 0, lowprobe = 0, eval = 0;
int c;
- blkid_loff_t offset = 0, size = 0;
+ uintmax_t offset = 0, size = 0;
show[0] = NULL;
- while ((c = getopt (argc, argv, "c:f:ghlL:o:O:ps:S:t:u:U:w:v")) != EOF)
+ while ((c = getopt (argc, argv, "c:f:ghilL:n:o:O:ps:S:t:u:U:w:v")) != EOF)
switch (c) {
case 'c':
if (optarg && !*optarg)
@@ -554,7 +682,18 @@ int main(int argc, char **argv)
search_value = strdup(optarg);
search_type = strdup("LABEL");
break;
+ case 'n':
+ if (fltr_usage) {
+ fprintf(stderr, "error: -u and -n options are mutually exclusive\n");
+ exit(4);
+ }
+ fltr_type = list_to_types(optarg, &fltr_flag);
+ break;
case 'u':
+ if (fltr_type) {
+ fprintf(stderr, "error: -u and -n options are mutually exclusive\n");
+ exit(4);
+ }
fltr_usage = list_to_usage(optarg, &fltr_flag);
break;
case 'U':
@@ -562,6 +701,9 @@ int main(int argc, char **argv)
search_value = strdup(optarg);
search_type = strdup("UUID");
break;
+ case 'i':
+ lowprobe |= LOWPROBE_TOPOLOGY;
+ break;
case 'l':
lookup++;
break;
@@ -577,6 +719,8 @@ int main(int argc, char **argv)
output_format = OUTPUT_PRETTY_LIST;
else if (!strcmp(optarg, "udev"))
output_format = OUTPUT_UDEV_LIST;
+ else if (!strcmp(optarg, "export"))
+ output_format = OUTPUT_EXPORT_LIST;
else if (!strcmp(optarg, "full"))
output_format = 0;
else {
@@ -587,10 +731,13 @@ int main(int argc, char **argv)
}
break;
case 'O':
- offset = strtoll(optarg, NULL, 10);
+ if (strtosize(optarg, &offset))
+ fprintf(stderr,
+ "Invalid offset '%s' specified\n",
+ optarg);
break;
case 'p':
- lowprobe++;
+ lowprobe |= LOWPROBE_SUPERBLOCKS;
break;
case 's':
if (numtag + 1 >= sizeof(show) / sizeof(*show)) {
@@ -601,7 +748,10 @@ int main(int argc, char **argv)
show[numtag] = NULL;
break;
case 'S':
- size = strtoll(optarg, NULL, 10);
+ if (strtosize(optarg, &size))
+ fprintf(stderr,
+ "Invalid size '%s' specified\n",
+ optarg);
break;
case 't':
if (search_type) {
@@ -656,7 +806,7 @@ int main(int argc, char **argv)
}
err = 2;
- if (eval == 0 && output_format & OUTPUT_PRETTY_LIST) {
+ if (eval == 0 && (output_format & OUTPUT_PRETTY_LIST)) {
if (lowprobe) {
fprintf(stderr, "The low-level probing mode does not "
"support 'list' output format\n");
@@ -676,22 +826,35 @@ int main(int argc, char **argv)
"requires a device\n");
exit(4);
}
+
+ /* automatically enable 'export' format for I/O Limits */
+ if (!output_format && (lowprobe & LOWPROBE_TOPOLOGY))
+ output_format = OUTPUT_EXPORT_LIST;
+
pr = blkid_new_probe();
if (!pr)
goto exit;
- blkid_probe_set_superblocks_flags(pr,
+ if (lowprobe & LOWPROBE_SUPERBLOCKS) {
+ blkid_probe_set_superblocks_flags(pr,
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION);
- if (fltr_usage &&
- blkid_probe_filter_superblocks_usage(pr, fltr_flag, fltr_usage))
- goto exit;
+ if (fltr_usage && blkid_probe_filter_superblocks_usage(
+ pr, fltr_flag, fltr_usage))
+ goto exit;
+
+ else if (fltr_type && blkid_probe_filter_superblocks_type(
+ pr, fltr_flag, fltr_type))
+ goto exit;
+ }
for (i = 0; i < numdev; i++)
- err = lowprobe_device(pr, devices[i], show,
- output_format, offset, size);
+ err = lowprobe_device(pr, devices[i], lowprobe, show,
+ output_format,
+ (blkid_loff_t) offset,
+ (blkid_loff_t) size);
blkid_free_probe(pr);
} else if (eval) {
/*
@@ -757,6 +920,7 @@ int main(int argc, char **argv)
exit:
free(search_type);
free(search_value);
+ free_types_list(fltr_type);
if (!lowprobe && !eval)
blkid_put_cache(cache);
return err;
diff --git a/misc-utils/cal.c b/misc-utils/cal.c
index 5444ceaf..65d517a8 100644
--- a/misc-utils/cal.c
+++ b/misc-utils/cal.c
@@ -67,6 +67,7 @@
#include "c.h"
#include "nls.h"
+#include "mbsalign.h"
#if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW)
@@ -243,8 +244,8 @@ struct fmt_st
};
char * ascii_day(char *, int);
-int center_str(const char* src, char* dest, size_t dest_size, int width);
-void center(const char *, int, int);
+int center_str(const char* src, char* dest, size_t dest_size, size_t width);
+void center(const char *, size_t, int);
void day_array(int, int, int, int *);
int day_in_week(int, int, int);
int day_in_year(int, int, int);
@@ -312,7 +313,11 @@ main(int argc, char **argv) {
POSIX: 19971201 + 7 -1 = 0
*/
{
- int wfd = (int)(intptr_t) nl_langinfo(_NL_TIME_WEEK_1STDAY);
+ int wfd;
+ union { unsigned int word; char *string; } val;
+ val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY);
+
+ wfd = val.word;
wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100));
weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7;
}
@@ -749,95 +754,22 @@ trim_trailing_spaces(s)
*p = '\0';
}
-#ifdef HAVE_WIDECHAR
-/* replace non printable chars.
- * return 1 if replacement made, 0 otherwise */
-int wc_ensure_printable(wchar_t* wchars)
-{
- int replaced=0;
- wchar_t* wc = wchars;
- while (*wc) {
- if (!iswprint((wint_t) *wc)) {
- *wc=L'\uFFFD';
- replaced=1;
- }
- wc++;
- }
- return replaced;
-}
-
-/* truncate wchar string to width cells.
- * returns number of cells used. */
-size_t wc_truncate(wchar_t* wchars, size_t width, size_t minchars)
-{
- int wc=0;
- int cells=0;
- while (*(wchars+wc)) {
- cells = wcswidth(wchars, wc+1);
- if (cells > width) {
- if (wc >= minchars) {
- break;
- }
- }
- wc++;
- }
- wchars[wc]=L'\0';
- return cells;
-}
-#endif
-
/*
* Center string, handling multibyte characters appropriately.
* In addition if the string is too large for the width it's truncated.
* The number of trailing spaces may be 1 less than the number of leading spaces.
*/
int
-center_str(const char* src, char* dest, size_t dest_size, int width)
+center_str(const char* src, char* dest, size_t dest_size, size_t width)
{
-#ifdef HAVE_WIDECHAR
- wchar_t str_wc[FMT_ST_CHARS];
-#endif
- char str[FMT_ST_CHARS];
- const char* str_to_print=src;
- int used, spaces, wc_conversion=0, wc_enabled=0;
-
-#ifdef HAVE_WIDECHAR
- if (mbstowcs(str_wc, src, ARRAY_SIZE(str_wc)) > 0) {
- str_wc[ARRAY_SIZE(str_wc)-1]=L'\0';
- wc_enabled=1;
- wc_conversion = wc_ensure_printable(str_wc);
- used = wcswidth(str_wc, ARRAY_SIZE(str_wc));
- }
- else
-#endif
- used = strlen(src);
-
- if (wc_conversion || used > width) {
- str_to_print=str;
- if (wc_enabled) {
-#ifdef HAVE_WIDECHAR
- used = wc_truncate(str_wc, width, 1);
- wcstombs(str, str_wc, ARRAY_SIZE(str));
-#endif
- } else {
- memcpy(str, src, width);
- str[width]='\0';
- }
- }
-
- spaces = width - used;
- spaces = ( spaces < 0 ? 0 : spaces );
-
- return snprintf(dest, dest_size, "%*s%s%*s",
- spaces / 2 + spaces % 2, "",
- str_to_print,
- spaces / 2, "" );
+ return mbsalign(src, dest, dest_size, &width,
+ MBS_ALIGN_CENTER, MBA_UNIBYTE_FALLBACK);
}
void
center(str, len, separate)
const char *str;
- int len;
+ size_t len;
int separate;
{
char lineout[FMT_ST_CHARS];
diff --git a/misc-utils/logger.1 b/misc-utils/logger.1
index 5245afb9..1119f62d 100644
--- a/misc-utils/logger.1
+++ b/misc-utils/logger.1
@@ -98,10 +98,10 @@ 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.
+Valid facility names are: auth, authpriv (for security information of a
+sensitive nature), cron, daemon, ftp, kern (can’t be generated from user
+process), 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),
diff --git a/misc-utils/script.1 b/misc-utils/script.1
index e017b63b..24c6b572 100644
--- a/misc-utils/script.1
+++ b/misc-utils/script.1
@@ -41,6 +41,7 @@
.Nm script
.Op Fl a
.Op Fl c Ar COMMAND
+.Op Fl e
.Op Fl f
.Op Fl q
.Op Fl t
@@ -74,6 +75,9 @@ retaining the prior contents.
Run the COMMAND rather than an interactive shell.
This makes it easy for a script to capture the output of a program that
behaves differently when its stdout is not a tty.
+.It Fl e
+Return the exit code of the child process. Uses the same format as bash
+termination on signal termination exit code is 128+n.
.It Fl f
Flush output after each write. This is nice for telecooperation:
One person does `mkfifo foo; script -f foo' and another can
diff --git a/misc-utils/script.c b/misc-utils/script.c
index b877c312..2028db66 100644
--- a/misc-utils/script.c
+++ b/misc-utils/script.c
@@ -59,11 +59,14 @@
#include "nls.h"
-
#ifdef HAVE_LIBUTIL
#include <pty.h>
#endif
+#ifdef HAVE_LIBUTEMPTER
+#include <utempter.h>
+#endif
+
void finish(int);
void done(void);
void fail(void);
@@ -77,10 +80,11 @@ void doshell(void);
char *shell;
FILE *fscript;
-int master;
+int master = -1;
int slave;
int child;
int subchild;
+int childstatus;
char *fname;
struct termios tt;
@@ -92,6 +96,7 @@ char line[] = "/dev/ptyXX";
#endif
int aflg = 0;
char *cflg = NULL;
+int eflg = 0;
int fflg = 0;
int qflg = 0;
int tflg = 0;
@@ -127,6 +132,7 @@ die_if_link(char *fn) {
int
main(int argc, char **argv) {
+ sigset_t block_mask, unblock_mask;
struct sigaction sa;
extern int optind;
char *p;
@@ -150,7 +156,7 @@ main(int argc, char **argv) {
}
}
- while ((ch = getopt(argc, argv, "ac:fqt")) != -1)
+ while ((ch = getopt(argc, argv, "ac:efqt")) != -1)
switch((char)ch) {
case 'a':
aflg++;
@@ -158,6 +164,9 @@ main(int argc, char **argv) {
case 'c':
cflg = optarg;
break;
+ case 'e':
+ eflg++;
+ break;
case 'f':
fflg++;
break;
@@ -170,7 +179,7 @@ main(int argc, char **argv) {
case '?':
default:
fprintf(stderr,
- _("usage: script [-a] [-f] [-q] [-t] [file]\n"));
+ _("usage: script [-a] [-e] [-f] [-q] [-t] [file]\n"));
exit(1);
}
argc -= optind;
@@ -196,19 +205,33 @@ main(int argc, char **argv) {
printf(_("Script started, file is %s\n"), fname);
fixtty();
+#ifdef HAVE_LIBUTEMPTER
+ utempter_add_record(master, NULL);
+#endif
+ /* setup SIGCHLD handler */
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
-
sa.sa_handler = finish;
sigaction(SIGCHLD, &sa, NULL);
+ /* init mask for SIGCHLD */
+ sigprocmask(SIG_SETMASK, NULL, &block_mask);
+ sigaddset(&block_mask, SIGCHLD);
+
+ sigprocmask(SIG_SETMASK, &block_mask, &unblock_mask);
child = fork();
+ sigprocmask(SIG_SETMASK, &unblock_mask, NULL);
+
if (child < 0) {
perror("fork");
fail();
}
if (child == 0) {
+
+ sigprocmask(SIG_SETMASK, &block_mask, NULL);
subchild = child = fork();
+ sigprocmask(SIG_SETMASK, &unblock_mask, NULL);
+
if (child < 0) {
perror("fork");
fail();
@@ -233,9 +256,6 @@ doinput() {
(void) fclose(fscript);
- if (die == 0 && child && kill(child, 0) == -1 && errno == ESRCH)
- die = 1;
-
while (die == 0) {
if ((cc = read(0, ibuf, BUFSIZ)) > 0) {
ssize_t wrt = write(master, ibuf, cc);
@@ -263,8 +283,10 @@ finish(int dummy) {
register int pid;
while ((pid = wait3(&status, WNOHANG, 0)) > 0)
- if (pid == child)
+ if (pid == child) {
+ childstatus = status;
die = 1;
+ }
}
void
@@ -303,17 +325,6 @@ dooutput() {
my_strftime(obuf, sizeof obuf, "%c\n", localtime(&tvec));
fprintf(fscript, _("Script started on %s"), obuf);
- if (die == 0 && child && kill(child, 0) == -1 && errno == ESRCH)
- /*
- * the SIGCHLD handler could be executed when the "child"
- * variable is not set yet. It means that the "die" is zero
- * althought the child process is already done. We have to
- * check this thing now. Now we have the "child" variable
- * already initialized. For more details see main() and
- * finish(). --kzak 07-Aug-2007
- */
- die = 1;
-
do {
if (die && flgs == 0) {
/* ..child is dead, but it doesn't mean that there is
@@ -386,6 +397,8 @@ doshell() {
(void) dup2(slave, 2);
(void) close(slave);
+ master = -1;
+
shname = strrchr(shell, '/');
if (shname)
shname++;
@@ -431,10 +444,23 @@ done() {
}
(void) fclose(fscript);
(void) close(master);
+
+ master = -1;
} else {
(void) tcsetattr(0, TCSADRAIN, &tt);
if (!qflg)
printf(_("Script done, file is %s\n"), fname);
+#ifdef HAVE_LIBUTEMPTER
+ if (master >= 0)
+ utempter_remove_record(master);
+#endif
+ }
+
+ if(eflg) {
+ if (WIFSIGNALED(childstatus))
+ exit(WTERMSIG(childstatus) + 0x80);
+ else
+ exit(WEXITSTATUS(childstatus));
}
exit(0);
}
@@ -476,9 +502,11 @@ getmaster() {
return;
}
(void) close(master);
+ master = -1;
}
}
}
+ master = -1;
fprintf(stderr, _("Out of pty's\n"));
fail();
#endif /* not HAVE_LIBUTIL */
diff --git a/misc-utils/wipefs.8 b/misc-utils/wipefs.8
index 3217c101..973f2ef2 100644
--- a/misc-utils/wipefs.8
+++ b/misc-utils/wipefs.8
@@ -15,7 +15,7 @@ wipefs \- wipe a filesystem signature from a device
.B wipefs
allows to erase filesystem or raid signatures (magic strings) from the
.I device
-to make the device invisible for libblkid.
+to make the filesystem invisible for libblkid.
.B wipefs
does not erase the whole filesystem or any other data from the device.
When used without options -a or -o, it lists all visible filesystems and offsets
@@ -31,6 +31,10 @@ Causes everything to be done except for the write() call.
Specifies location (in bytes) of the signature which should be erased from the
device. The offset number may include a "0x" prefix, and then the number will be
read as a hex value. It is possible to specify multiple -o options.
+
+The \fIoffset\fR argument may be followed by binary (2^N) suffixes KiB, MiB,
+GiB, TiB, PiB and EiB (the "iB" is optional, e.g. "K" has the same meaning as
+"KiB") or decimal (10^N) suffixes KB, MB, GB, PB and EB.
.IP "\fB\-p, \-\-parsable\fP"
Print out in parsable instead of printable format. Encode all potentially unsafe
characters of a string to the corresponding hex value prefixed by '\\x'.
diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c
index f735065d..4d850501 100644
--- a/misc-utils/wipefs.c
+++ b/misc-utils/wipefs.c
@@ -4,9 +4,10 @@
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
* Written by Karel Zak <kzak@redhat.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -33,6 +34,7 @@
#include <blkid.h>
#include "nls.h"
+#include "strtosize.h"
struct wipe_desc {
loff_t offset; /* magic string offset */
@@ -208,7 +210,7 @@ read_offsets(struct wipe_desc *wp, const char *fname, int zap)
if (rc == 0) {
const char *type = NULL;
blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL);
- errx(EXIT_FAILURE, _("error: %s: appears to contain '%s' "
+ warnx(_("WARNING: %s: appears to contain '%s' "
"partition table"), fname, type);
}
@@ -304,26 +306,18 @@ do_wipe(struct wipe_desc *wp, const char *fname, int noact)
static loff_t
strtoll_offset(const char *str)
{
- char *end = NULL;
- loff_t off;
+ uintmax_t sz;
- errno = 0;
- off = strtoll(str, &end, 0);
-
- if ((errno == ERANGE && (off == LLONG_MAX || off == LONG_MIN)) ||
- (errno != 0 && off == 0))
- err(EXIT_FAILURE, _("invalid offset '%s' value specified"), str);
-
- if (*end != '\0')
+ if (strtosize(str, &sz))
errx(EXIT_FAILURE, _("invalid offset '%s' value specified"), str);
-
- return off;
+ return sz;
}
+
static void __attribute__((__noreturn__))
usage(FILE *out)
{
- fprintf(out, _("Usage: %s [options] <filename>\n\nOptions:\n"),
+ fprintf(out, _("Usage: %s [options] <device>\n\nOptions:\n"),
program_invocation_short_name);
fprintf(out, _(
diff --git a/mount/Makefile.am b/mount/Makefile.am
index 70107200..1fbdfe82 100644
--- a/mount/Makefile.am
+++ b/mount/Makefile.am
@@ -16,7 +16,7 @@ hdrs_mount = fstab.h mount_mntent.h mount_constants.h \
# generic sources for mount and umount
srcs_mount = fstab.c mount_mntent.c getusername.c lomount.c devname.c devname.h \
$(srcs_common) $(hdrs_mount) ../lib/env.c ../lib/linux_version.c \
- ../lib/blkdev.c ../lib/fsprobe.c
+ ../lib/blkdev.c ../lib/fsprobe.c ../lib/mangle.c
# generic flags for all programs (except losetup)
# -- note that pkg-config autoconf macros (pkg.m4) does not differentiate
@@ -26,7 +26,7 @@ ldadd_static =
cflags_common = $(AM_CFLAGS)
ldflags_static = -all-static
-mount_SOURCES = mount.c $(srcs_mount) ../lib/setproctitle.c
+mount_SOURCES = mount.c $(srcs_mount) ../lib/setproctitle.c ../lib/strtosize.c
mount_CFLAGS = $(SUID_CFLAGS) $(cflags_common)
mount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
mount_LDADD = $(ldadd_common)
@@ -37,11 +37,12 @@ umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
umount_LDADD = $(ldadd_common)
swapon_SOURCES = swapon.c swap_constants.h ../lib/linux_version.c \
- ../lib/blkdev.c ../lib/fsprobe.c ../lib/canonicalize.c
+ ../lib/blkdev.c ../lib/fsprobe.c ../lib/canonicalize.c \
+ ../lib/mangle.c
swapon_CFLAGS = $(cflags_common)
swapon_LDADD = $(ldadd_common)
-losetup_SOURCES = lomount.c $(srcs_common) loop.h lomount.h
+losetup_SOURCES = lomount.c $(srcs_common) loop.h lomount.h ../lib/strtosize.c
losetup_CPPFLAGS = -DMAIN $(AM_CPPFLAGS)
mount_static_LDADD =
diff --git a/mount/fstab.c b/mount/fstab.c
index 8cd35d64..97d64a2c 100644
--- a/mount/fstab.c
+++ b/mount/fstab.c
@@ -55,7 +55,7 @@ mtab_does_not_exist(void) {
return var_mtab_does_not_exist;
}
-static int
+int
mtab_is_a_symlink(void) {
get_mtab_info();
return var_mtab_is_a_symlink;
diff --git a/mount/fstab.h b/mount/fstab.h
index 8fc8fd41..38f7bab9 100644
--- a/mount/fstab.h
+++ b/mount/fstab.h
@@ -3,6 +3,7 @@
#include "mount_mntent.h"
int mtab_is_writable(void);
+int mtab_is_a_symlink(void);
int mtab_does_not_exist(void);
void reset_mtab_info(void);
int is_mounted_once(const char *name);
diff --git a/mount/lomount.c b/mount/lomount.c
index 90bc92c0..db6d5326 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -950,6 +950,8 @@ find_unused_loop_device (void) {
#include <getopt.h>
#include <stdarg.h>
+#include "strtosize.h"
+
static void
usage(void) {
fprintf(stderr, _("\nUsage:\n"
@@ -991,7 +993,7 @@ main(int argc, char **argv) {
int pfd = -1;
int keysz = 0;
int hash_pass = 1;
- unsigned long long off, slimit;
+ uintmax_t off = 0, slimit = 0;
struct option longopts[] = {
{ "all", 0, 0, 'a' },
{ "set-capacity", 0, 0, 'c' },
@@ -1017,8 +1019,6 @@ main(int argc, char **argv) {
textdomain(PACKAGE);
capacity = delete = find = all = 0;
- off = 0;
- slimit = 0;
assoc = offset = sizelimit = encryption = passfd = NULL;
keysize = NULL;
@@ -1102,11 +1102,15 @@ main(int argc, char **argv) {
usage();
}
- if (offset && sscanf(offset, "%llu", &off) != 1)
+ if (offset && strtosize(offset, &off)) {
+ error(_("%s: invalid offset '%s' specified"), progname, offset);
usage();
-
- if (sizelimit && sscanf(sizelimit, "%llu", &slimit) != 1)
+ }
+ if (sizelimit && strtosize(sizelimit, &slimit)) {
+ error(_("%s: invalid sizelimit '%s' specified"),
+ progname, sizelimit);
usage();
+ }
if (all)
return show_used_loop_devices();
diff --git a/mount/losetup.8 b/mount/losetup.8
index f42afe5a..47d3cd46 100644
--- a/mount/losetup.8
+++ b/mount/losetup.8
@@ -39,7 +39,7 @@ Setup loop device:
.RB [ \-o
.IR offset ]
.RB [ \-\-sizelimit
-.IR limit ]
+.IR size ]
.in +8
.RB [ \-p
.IR pfd ]
@@ -78,6 +78,10 @@ When the cryptoloop module is loaded (or compiled in), it uses number 18.
This cryptoloop module will take the name of an arbitrary encryption type
and find the module that knows how to perform that encryption.
.SH OPTIONS
+The \fIsize\fR and \fIoffset\fR arguments may be followed by binary (2^N)
+suffixes KiB, MiB, GiB, TiB, PiB and EiB (the "iB" is optional, e.g. "K" has the
+same meaning as "KiB") or decimal (10^N) suffixes KB, MB, GB, PB and EB.
+
.IP "\fB\-a, \-\-all\fP"
show status of all loop devices
.IP "\fB\-c, \-\-set-capacity\fP \fIloopdev\fP
@@ -103,8 +107,8 @@ hash function, non-Debian systems tend not to.
.IP "\fB\-o, \-\-offset \fIoffset\fP"
the data start is moved \fIoffset\fP bytes into the specified file or
device
-.IP "\fB\-\-sizelimit \fIlimit\fP"
-the data end is set to no more than \fIsizelimit\fP bytes after the data start
+.IP "\fB\-\-sizelimit \fIsize\fP"
+the data end is set to no more than \fIsize\fP bytes after the data start
.IP "\fB\-p, \-\-pass-fd \fInum\fP"
read the passphrase from file descriptor with number
.I num
diff --git a/mount/mount.8 b/mount/mount.8
index bb807167..bf5a419a 100644
--- a/mount/mount.8
+++ b/mount/mount.8
@@ -199,6 +199,34 @@ If no arguments are given to
.BR mount ,
this list is printed.
+The
+.B mount
+program does not read the
+.I /etc/fstab
+file if
+.I device
+(or LABEL/UUID) and
+.I dir
+are specified. For example:
+.RS
+.sp
+.B "mount /dev/foo /dir"
+.sp
+.RE
+If you want to override mount options from
+.I /etc/fstab
+you have to use:
+.RS
+.sp
+.B "mount device|dir -o <options>"
+.sp
+.RE
+and then the mount options from command line will be appended to
+the list of options from
+.IR /etc/fstab .
+The usual behaviour is that the last option wins if there is more duplicated
+options.
+
When the
.I proc
filesystem is mounted (say at
@@ -2251,6 +2279,7 @@ is: ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12).
.TP
.B posix
Allow two files with names that only differ in case.
+This option is obsolete.
.TP
.B nonumtail
First try to make a short name without sequence number,
@@ -2517,18 +2546,38 @@ Since Linux version 2.1.21 xiafs is no longer part of the kernel source.
.SH "THE LOOP DEVICE"
One further possible type is a mount via the loop device. For example,
the command
-
-.nf
-.B " mount /tmp/fdimage /mnt -t vfat -o loop=/dev/loop3
-.fi
-
+.RS
+.sp
+.B "mount /tmp/disk.img /mnt -t vfat -o loop=/dev/loop"
+.sp
+.RE
will set up the loop device
.I /dev/loop3
to correspond to the file
-.IR /tmp/fdimage ,
+.IR /tmp/disk.img ,
and then mount this device on
.IR /mnt .
+If no explicit loop device is mentioned
+(but just an option `\fB\-o loop\fP' is given), then
+.B mount
+will try to find some unused loop device and use that, for example
+.RS
+.sp
+.B "mount /tmp/disk.img /mnt -o loop"
+.sp
+.RE
+The mount command
+.B automatically
+creates a loop device from a regular file if a filesystem type is
+not specified or the filesystem is known for libblkid, for example:
+.RS
+.sp
+.B "mount /tmp/disk.img /mnt"
+.sp
+.B "mount -t ext3 /tmp/disk.img /mnt"
+.sp
+.RE
This type of mount knows about four options, namely
.BR loop ", " offset ", " sizelimit " and " encryption ,
that are really options to
@@ -2540,11 +2589,6 @@ option.
(These options can be used in addition to those specific
to the filesystem type.)
-If no explicit loop device is mentioned
-(but just an option `\fB\-o loop\fP' is given), then
-.B mount
-will try to find some unused loop device and use that.
-
Since Linux 2.6.25 is supported auto-destruction of loop devices and
then any loop device allocated by
.B mount
diff --git a/mount/mount.c b/mount/mount.c
index 464ca54f..26a8afed 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -41,6 +41,7 @@
#include "env.h"
#include "nls.h"
#include "blkdev.h"
+#include "strtosize.h"
#define DO_PS_FIDDLING
@@ -211,6 +212,7 @@ static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_sizelimit,
*opt_encryption, *opt_speed, *opt_comment, *opt_uhelper;
static const char *opt_keybits, *opt_nohashpass;
+static int is_readonly(const char *node);
static int mounted (const char *spec0, const char *node0);
static int check_special_mountprog(const char *spec, const char *node,
const char *type, int flags, char *extra_opts, int *status);
@@ -294,6 +296,14 @@ print_all (char *types) {
if (matching_type (mc->m.mnt_type, types))
print_one (&(mc->m));
}
+
+ if (!mtab_does_not_exist() && !mtab_is_a_symlink() && is_readonly(_PATH_MOUNTED))
+ printf(_("\n"
+ "mount: warning: /etc/mtab is not writable (e.g. read-only filesystem).\n"
+ " It's possible that information reported by mount(8) is not\n"
+ " up to date. For actual information about system mount points\n"
+ " check the /proc/mounts file.\n\n"));
+
exit (0);
}
@@ -747,8 +757,6 @@ static int
was_tested(const char *fstype) {
struct tried *t;
- if (fsprobe_known_fstype(fstype))
- return 1;
for (t = tried; t; t = t->next) {
if (!strcmp(t->type, fstype))
return 1;
@@ -785,8 +793,8 @@ procfsnext(FILE *procfs) {
char fsname[100];
while (fgets(line, sizeof(line), procfs)) {
- if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
- if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
+ if (sscanf (line, "nodev %[^#\n]\n", fsname) == 1) continue;
+ if (sscanf (line, " %[^# \n]\n", fsname) != 1) continue;
return xstrdup(fsname);
}
return 0;
@@ -889,9 +897,9 @@ procfsloop_mount(int (*mount_fn)(struct mountargs *, int *, int *),
}
static const char *
-guess_fstype_by_devname(const char *devname)
+guess_fstype_by_devname(const char *devname, int *ambivalent)
{
- const char *type = fsprobe_get_fstype_by_devname(devname);
+ const char *type = fsprobe_get_fstype_by_devname_ambi(devname, ambivalent);
if (verbose) {
printf (_("mount: you didn't specify a filesystem type for %s\n"), devname);
@@ -918,12 +926,13 @@ static int
guess_fstype_and_mount(const char *spec, const char *node, const char **types,
int flags, char *mount_opts, int *special, int *status) {
struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
+ int ambivalent = 0;
if (*types && strcasecmp (*types, "auto") == 0)
*types = NULL;
if (!*types && !(flags & MS_REMOUNT)) {
- *types = guess_fstype_by_devname(spec);
+ *types = guess_fstype_by_devname(spec, &ambivalent);
if (*types) {
if (!strcmp(*types, MNTTYPE_SWAP)) {
error(_("%s looks like swapspace - not mounted"), spec);
@@ -933,6 +942,11 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types,
args.type = *types;
return do_mount (&args, special, status);
}
+ } else if (ambivalent) {
+ error(_("mount: %s: more filesystems detected. This should not happen,\n"
+ " use -t <type> to explicitly specify the filesystem type or\n"
+ " use wipefs(8) to clean up the device.\n"), spec);
+ return 1;
}
}
@@ -1070,11 +1084,26 @@ is_mounted_same_loopfile(const char *node0, const char *loopfile, unsigned long
}
static int
+parse_offset(const char **opt, uintmax_t *val)
+{
+ char *tmp;
+
+ if (strtosize(*opt, val))
+ return -1;
+
+ tmp = xmalloc(32);
+ snprintf(tmp, 32, "%jd", *val);
+ my_free(*opt);
+ *opt = tmp;
+ return 0;
+}
+
+static int
loop_check(const char **spec, const char **type, int *flags,
int *loop, const char **loopdev, const char **loopfile,
const char *node) {
int looptype;
- unsigned long long offset, sizelimit;
+ uintmax_t offset = 0, sizelimit = 0;
/*
* In the case of a loop mount, either type is of the form lo@/dev/loop5
@@ -1102,6 +1131,21 @@ loop_check(const char **spec, const char **type, int *flags,
*loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_sizelimit || opt_encryption || opt_keybits);
*loopfile = *spec;
+ /* Automatically create a loop device from a regular file if a filesystem
+ * is not specified or the filesystem is known for libblkid (these
+ * filesystems work with block devices only).
+ *
+ * Note that there is not a restriction (on kernel side) that prevents regular
+ * file as a mount(2) source argument. A filesystem that is able to mount
+ * regular files could be implemented.
+ */
+ if (!*loop && (!*type || strcmp(*type, "auto") == 0 ||
+ fsprobe_known_fstype(*type))) {
+ struct stat st;
+ if (stat(*loopfile, &st) == 0)
+ *loop = S_ISREG(st.st_mode);
+ }
+
if (*loop) {
*flags |= MS_LOOP;
if (fake) {
@@ -1114,8 +1158,14 @@ loop_check(const char **spec, const char **type, int *flags,
if (*flags & MS_RDONLY)
loop_opts |= SETLOOP_RDONLY;
- offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
- sizelimit = opt_sizelimit ? strtoull(opt_sizelimit, NULL, 0) : 0;
+ if (opt_offset && parse_offset(&opt_offset, &offset)) {
+ error(_("mount: invalid offset '%s' specified"), opt_offset);
+ return EX_FAIL;
+ }
+ if (opt_sizelimit && parse_offset(&opt_sizelimit, &sizelimit)) {
+ error(_("mount: invalid sizelimit '%s' specified"), opt_sizelimit);
+ return EX_FAIL;
+ }
if (is_mounted_same_loopfile(node, *loopfile, offset)) {
error(_("mount: according to mtab %s is already mounted on %s as loop"), *loopfile, node);
@@ -1311,7 +1361,6 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
int loop = 0;
const char *loopdev = 0, *loopfile = 0;
struct stat statbuf;
- int retries = 0; /* Nr of retries for mount in case of ENOMEDIUM */
/* copies for freeing on exit */
const char *opts1, *spec1, *node1, *types1, *extra_opts1;
@@ -1377,7 +1426,6 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
goto out;
}
-mount_retry:
block_signals (SIG_BLOCK);
if (!fake) {
@@ -1577,7 +1625,7 @@ mount_retry:
error (_("mount: %s is not a block device, and stat fails?"), spec);
else if (S_ISBLK(statbuf.st_mode))
error (_("mount: the kernel does not recognize %s as a block device\n"
- " (maybe `insmod driver'?)"), spec);
+ " (maybe `modprobe driver'?)"), spec);
else if (S_ISREG(statbuf.st_mode))
error (_("mount: %s is not a block device (maybe try `-o loop'?)"),
spec);
@@ -1623,14 +1671,6 @@ mount_retry:
break;
}
case ENOMEDIUM:
- if (retries < CRDOM_NOMEDIUM_RETRIES) {
- if (verbose)
- printf(_("mount: no medium found on %s ...trying again\n"),
- spec);
- sleep(3);
- ++retries;
- goto mount_retry;
- }
error(_("mount: no medium found on %s"), spec);
break;
default:
diff --git a/mount/mount_mntent.c b/mount/mount_mntent.c
index f2623fd5..08e5bf48 100644
--- a/mount/mount_mntent.c
+++ b/mount/mount_mntent.c
@@ -9,42 +9,11 @@
#include <string.h> /* for index */
#include <ctype.h> /* for isdigit */
#include <sys/stat.h> /* for umask */
+
#include "mount_mntent.h"
#include "sundries.h" /* for xmalloc */
#include "nls.h"
-
-/* Unfortunately the classical Unix /etc/mtab and /etc/fstab
- do not handle directory names containing spaces.
- Here we mangle them, replacing a space by \040.
- What do other Unices do? */
-
-static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
-
-static char *
-mangle(const char *s) {
- char *ss, *sp;
- int n;
-
- n = strlen(s);
- ss = sp = xmalloc(4*n+1);
- while(1) {
- for (n = 0; n < sizeof(need_escaping); n++) {
- if (*s == need_escaping[n]) {
- *sp++ = '\\';
- *sp++ = '0' + ((*s & 0300) >> 6);
- *sp++ = '0' + ((*s & 070) >> 3);
- *sp++ = '0' + (*s & 07);
- goto next;
- }
- }
- *sp++ = *s;
- if (*s == 0)
- break;
- next:
- s++;
- }
- return ss;
-}
+#include "mangle.h"
static int
is_space_or_tab (char c) {
@@ -65,26 +34,6 @@ skip_nonspaces(char *s) {
return s;
}
-#define isoctal(a) (((a) & ~7) == '0')
-
-/* returns malloced pointer - no more strdup required */
-static char *
-unmangle(char *s) {
- char *ret, *ss, *sp;
-
- ss = skip_nonspaces(s);
- ret = sp = xmalloc(ss-s+1);
- while(s != ss) {
- if (*s == '\\' && isoctal(s[1]) && isoctal(s[2]) && isoctal(s[3])) {
- *sp++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
- s += 4;
- } else
- *sp++ = *s++;
- }
- *sp = 0;
- return ret;
-}
-
/*
* fstat'ing the file and allocating a buffer holding all of it
* may be a bad idea: if the file is /proc/mounts, the stat
diff --git a/mount/swapon.c b/mount/swapon.c
index 75ba8653..4ee3c2f7 100644
--- a/mount/swapon.c
+++ b/mount/swapon.c
@@ -22,6 +22,7 @@
#include "fsprobe.h"
#include "pathnames.h"
#include "swapheader.h"
+#include "mangle.h"
#define PATH_MKSWAP "/sbin/mkswap"
@@ -125,6 +126,7 @@ read_proc_swaps(void) {
FILE *swaps;
char line[1024];
char *p, **q;
+ size_t sz;
numSwaps = 0;
swapFiles = NULL;
@@ -152,14 +154,24 @@ read_proc_swaps(void) {
* This will fail with names with embedded spaces.
*/
for (p = line; *p && *p != ' '; p++);
- *p = 0;
+ *p = '\0';
+
+ /* the kernel can use " (deleted)" suffix for paths
+ * in /proc/swaps, we have to remove this junk.
+ */
+ sz = strlen(line);
+ if (sz > PATH_DELETED_SUFFIX_SZ) {
+ p = line + (sz - PATH_DELETED_SUFFIX_SZ);
+ if (strcmp(p, PATH_DELETED_SUFFIX) == 0)
+ *p = '\0';
+ }
q = realloc(swapFiles, (numSwaps+1) * sizeof(*swapFiles));
if (q == NULL)
break;
swapFiles = q;
- swapFiles[numSwaps++] = strdup(line);
+ swapFiles[numSwaps++] = unmangle(line);
}
fclose(swaps);
}
@@ -354,7 +366,7 @@ swap_get_size(const char *hdr, const char *devname, unsigned int pagesize)
pagesize / 1024,
flip ? _("different") : _("same"));
- return (last_page + 1) * pagesize;
+ return ((unsigned long long) last_page + 1) * pagesize;
}
static int
diff --git a/mount/umount.8 b/mount/umount.8
index aa904112..5ef861aa 100644
--- a/mount/umount.8
+++ b/mount/umount.8
@@ -123,6 +123,12 @@ anymore.
Don't canonicalize paths. For more details about this option see the
.B mount(8)
man page.
+.IP "\fB\-\-fake\fP"
+Causes everything to be done except for the actual system call; this
+``fakes'' unmounting the filesystem. It can be used to remove
+entries from
+.I /etc/mtab
+that were unmounted earlier with the -n option.
.SH "THE LOOP DEVICE"
The
diff --git a/mount/umount.c b/mount/umount.c
index 7f146558..6786ac57 100644
--- a/mount/umount.c
+++ b/mount/umount.c
@@ -81,6 +81,9 @@ int restricted = 1;
int complained_err = 0;
char *complained_dev = NULL;
+/* True for fake umount (--fake). */
+static int fake = 0;
+
/*
* check_special_umountprog()
* If there is a special umount program for this type, exec it.
@@ -187,7 +190,7 @@ umount_one (const char *spec, const char *node, const char *type,
const char *opts, struct mntentchn *mc) {
int umnt_err = 0;
int isroot;
- int res;
+ int res = 0;
int status;
const char *loopdev;
int myloop = 0;
@@ -210,6 +213,9 @@ umount_one (const char *spec, const char *node, const char *type,
if (check_special_umountprog(spec, node, type, &status))
return status;
+ /* Skip the actual umounting for --fake */
+ if (fake)
+ goto writemtab;
/*
* Ignore the option "-d" for non-loop devices and loop devices with
* LO_FLAGS_AUTOCLEAR flag.
@@ -390,6 +396,7 @@ static struct option longopts[] =
{ "types", 1, 0, 't' },
{ "no-canonicalize", 0, 0, 144 },
+ { "fake", 0, 0, 145 },
{ NULL, 0, 0, 0 }
};
@@ -679,6 +686,9 @@ main (int argc, char *argv[]) {
case 144:
nocanonicalize = 1;
break;
+ case 145:
+ fake = 1;
+ break;
case 0:
break;
case '?':
@@ -697,7 +707,8 @@ main (int argc, char *argv[]) {
}
if (restricted &&
- (all || types || nomtab || force || remount || nocanonicalize)) {
+ (all || types || nomtab || force || remount || nocanonicalize ||
+ fake)) {
die (2, _("umount: only root can do that"));
}
diff --git a/partx/addpart.c b/partx/addpart.c
index 004fee53..112a2860 100644
--- a/partx/addpart.c
+++ b/partx/addpart.c
@@ -25,8 +25,8 @@ main(int argc, char **argv){
exit(1);
}
p.pno = atoi(argv[2]);
- p.start = 512 * ((long long) atol(argv[3]));
- p.length = 512 * ((long long) atol(argv[4]));
+ p.start = 512 * atoll(argv[3]);
+ p.length = 512 * atoll(argv[4]);
p.devname[0] = 0;
p.volname[0] = 0;
a.op = BLKPG_ADD_PARTITION;
diff --git a/partx/partx.c b/partx/partx.c
index 16ea1fab..14d2609f 100644
--- a/partx/partx.c
+++ b/partx/partx.c
@@ -178,6 +178,8 @@ main(int argc, char **argv){
while (upper == 0 || lower <= upper) {
int err;
+ if (lower > MAXSLICES)
+ break;
pt.pno = lower;
pt.start = 0;
pt.length = 0;
@@ -295,6 +297,9 @@ main(int argc, char **argv){
}
}
for (j=0; j<n; j++) {
+ /* skip unused/empty partitions */
+ if (slices[j].size == 0)
+ continue;
pt.pno = lower+j;
pt.start = 512 * (long long) slices[j].start;
pt.length = 512 * (long long) slices[j].size;
diff --git a/schedutils/ionice.c b/schedutils/ionice.c
index 082b23ba..3ad4ef9a 100644
--- a/schedutils/ionice.c
+++ b/schedutils/ionice.c
@@ -81,7 +81,7 @@ static void usage(int rc)
"\nionice - sets or gets process io scheduling class and priority.\n"
"\nUsage:\n"
" ionice [ options ] -p <pid> [<pid> ...]\n"
- " ionoce [ options ] <command> [<arg> ...]\n"
+ " ionice [ options ] <command> [<arg> ...]\n"
"\nOptions:\n"
" -n <classdata> class data (0-7, lower being higher prio)\n"
" -c <class> scheduling class\n"
@@ -184,7 +184,7 @@ int main(int argc, char *argv[])
ioprio_setpid(0, ioprio, ioclass);
execvp(argv[optind], &argv[optind]);
/* execvp should never return */
- err(EXIT_FAILURE, _("execvp failed"));
+ err(EXIT_FAILURE, _("executing %s failed"), argv[optind]);
}
}
diff --git a/shlibs/blkid/samples/partitions.c b/shlibs/blkid/samples/partitions.c
index c9587fe5..db1b5ff2 100644
--- a/shlibs/blkid/samples/partitions.c
+++ b/shlibs/blkid/samples/partitions.c
@@ -21,7 +21,7 @@ int main(int argc, char *argv[])
char *devname;
blkid_probe pr;
blkid_partlist ls;
- blkid_parttable root_tab = NULL;
+ blkid_parttable root_tab;
if (argc < 2) {
fprintf(stderr, "usage: %s <device|file> "
@@ -40,25 +40,32 @@ int main(int argc, char *argv[])
if (!ls)
errx(EXIT_FAILURE, "%s: failed to read partitions\n", devname);
+ /*
+ * Print info about the primary (root) partition table
+ */
+ root_tab = blkid_partlist_get_table(ls);
+ if (!root_tab)
+ errx(EXIT_FAILURE, "%s: does not contains any "
+ "known partition table\n", devname);
+
+ printf("size: %jd, sector size: %u, PT: %s, offset: %jd\n---\n",
+ blkid_probe_get_size(pr),
+ blkid_probe_get_sectorsize(pr),
+ blkid_parttable_get_type(root_tab),
+ blkid_parttable_get_offset(root_tab));
+
+ /*
+ * List partitions
+ */
nparts = blkid_partlist_numof_partitions(ls);
if (!nparts)
- errx(EXIT_FAILURE, "%s: does not contains any "
- "known partition table\n", devname);
+ goto done;
for (i = 0; i < nparts; i++) {
const char *p;
blkid_partition par = blkid_partlist_get_partition(ls, i);
blkid_parttable tab = blkid_partition_get_table(par);
- if (i == 0) {
- root_tab = tab;
- printf("size: %llu, sector size: %u, "
- "PT: %s, offset: %llu\n---\n",
- (unsigned long long) blkid_probe_get_size(pr),
- blkid_probe_get_sectorsize(pr),
- blkid_parttable_get_type(tab),
- (unsigned long long) blkid_parttable_get_offset(tab));
- }
printf("#%d: %10llu %10llu 0x%x",
blkid_partition_get_partno(par),
(unsigned long long) blkid_partition_get_start(par),
@@ -66,7 +73,7 @@ int main(int argc, char *argv[])
blkid_partition_get_type(par));
if (root_tab != tab)
- /* subpartition */
+ /* subpartition (BSD, Minix, ...) */
printf(" (%s)", blkid_parttable_get_type(tab));
p = blkid_partition_get_name(par);
@@ -82,7 +89,7 @@ int main(int argc, char *argv[])
putc('\n', stdout);
}
+done:
blkid_free_probe(pr);
-
return EXIT_SUCCESS;
}
diff --git a/shlibs/blkid/src/blkid.h.in b/shlibs/blkid/src/blkid.h.in
index 4e53b39f..7fa2fde6 100644
--- a/shlibs/blkid/src/blkid.h.in
+++ b/shlibs/blkid/src/blkid.h.in
@@ -197,9 +197,15 @@ extern int blkid_probe_set_device(blkid_probe pr, int fd,
blkid_loff_t off, blkid_loff_t size);
extern dev_t blkid_probe_get_devno(blkid_probe pr);
+extern dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr);
+extern int blkid_probe_is_wholedisk(blkid_probe pr);
+
extern blkid_loff_t blkid_probe_get_size(blkid_probe pr);
+extern blkid_loff_t blkid_probe_get_offset(blkid_probe pr);
extern unsigned int blkid_probe_get_sectorsize(blkid_probe pr);
+extern int blkid_probe_get_fd(blkid_probe pr);
+
/*
* superblocks probing
*/
@@ -260,14 +266,17 @@ extern int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *na
/* partitions probing flags */
-#define BLKID_PARTS_FORCE_GPT (1 << 1)
+#define BLKID_PARTS_FORCE_GPT (1 << 1)
+#define BLKID_PARTS_ENTRY_DETAILS (1 << 2)
extern int blkid_probe_set_partitions_flags(blkid_probe pr, int flags);
/* binary interface */
extern blkid_partlist blkid_probe_get_partitions(blkid_probe pr);
extern int blkid_partlist_numof_partitions(blkid_partlist ls);
+extern blkid_parttable blkid_partlist_get_table(blkid_partlist ls);
extern blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n);
+extern blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno);
extern blkid_parttable blkid_partition_get_table(blkid_partition par);
extern const char *blkid_partition_get_name(blkid_partition par);
@@ -277,6 +286,7 @@ extern blkid_loff_t blkid_partition_get_start(blkid_partition par);
extern blkid_loff_t blkid_partition_get_size(blkid_partition par);
extern int blkid_partition_get_type(blkid_partition par);
extern const char *blkid_partition_get_type_string(blkid_partition par);
+extern unsigned long long blkid_partition_get_flags(blkid_partition par);
extern int blkid_partition_is_logical(blkid_partition par);
extern int blkid_partition_is_extended(blkid_partition par);
extern int blkid_partition_is_primary(blkid_partition par);
diff --git a/shlibs/blkid/src/blkid.sym b/shlibs/blkid/src/blkid.sym
index 4d01aa20..4085d2ce 100644
--- a/shlibs/blkid/src/blkid.sym
+++ b/shlibs/blkid/src/blkid.sym
@@ -120,5 +120,12 @@ global:
*/
BLKID_2.18 {
global:
+ blkid_partition_get_flags;
+ blkid_partlist_devno_to_partition;
+ blkid_partlist_get_table;
blkid_probe_all_removable;
+ blkid_probe_get_fd;
+ blkid_probe_get_offset;
+ blkid_probe_get_wholedisk_devno;
+ blkid_probe_is_wholedisk;
} BLKID_2.17;
diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h
index d15b5305..41eba910 100644
--- a/shlibs/blkid/src/blkidP.h
+++ b/shlibs/blkid/src/blkidP.h
@@ -19,8 +19,10 @@
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
+#include <stdint.h>
#include "c.h"
#include "bitops.h" /* $(top_srcdir)/include/ */
@@ -44,6 +46,7 @@ struct blkid_struct_dev
int bid_pri; /* Device priority */
dev_t bid_devno; /* Device major/minor number */
time_t bid_time; /* Last update time of device */
+ suseconds_t bid_utime; /* Last update time (microseconds) */
unsigned int bid_flags; /* Device status bitflags */
char *bid_label; /* Shortcut to device LABEL */
char *bid_uuid; /* Shortcut to binary UUID */
@@ -118,7 +121,7 @@ struct blkid_chaindrv {
#define BLKID_NVALS_SUBLKS 14
#define BLKID_NVALS_TOPLGY 5
-#define BLKID_NVALS_PARTS 1
+#define BLKID_NVALS_PARTS 8
/* Max number of all values in probing result */
#define BLKID_NVALS (BLKID_NVALS_SUBLKS + \
@@ -188,10 +191,12 @@ struct blkid_struct_probe
blkid_loff_t size; /* end of data on the device */
dev_t devno; /* device number (st.st_rdev) */
+ dev_t disk_devno; /* devno of the whole-disk or 0 */
unsigned int blkssz; /* sector size (BLKSSZGET ioctl) */
mode_t mode; /* struct stat.sb_mode */
int flags; /* private libray flags */
+ int prob_flags; /* always zeroized by blkid_do_*() */
struct list_head buffers; /* list of buffers */
@@ -202,9 +207,12 @@ struct blkid_struct_probe
int nvals; /* number of assigned vals */
};
-/* flags */
+/* private flags */
#define BLKID_PRIVATE_FD (1 << 1) /* see blkid_new_probe_from_filename() */
#define BLKID_TINY_DEV (1 << 2) /* <= 1.47MiB (floppy or so) */
+#define BLKID_CDROM_DEV (1 << 3) /* is a CD/DVD drive */
+/* private probing flags */
+#define BLKID_PARTS_IGNORE_PT (1 << 1) /* ignore partition table */
/*
* Evaluation methods (for blkid_eval_* API)
@@ -312,7 +320,6 @@ extern int blkid_openat(DIR *dir, const char *dirname, const char *filename,
#define DEBUG_ALL 0xFFFF
#ifdef CONFIG_BLKID_DEBUG
-#include <stdio.h>
extern int blkid_debug_mask;
extern void blkid_init_debug(int mask);
extern void blkid_debug_dump_dev(blkid_dev dev);
@@ -332,6 +339,11 @@ struct dir_list {
};
extern void blkid__scan_dir(char *, dev_t, struct dir_list **, char **);
extern int blkid_driver_has_major(const char *drvname, int major);
+extern int blkid_devno_has_attribute(dev_t devno, const char *attribute);
+extern int blkid_devno_get_u64_attribute(dev_t devno, const char *attribute,
+ uint64_t *result);
+extern int blkid_devno_get_s64_attribute(dev_t devno, const char *attribute,
+ int64_t *result);
/* lseek.c */
extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
@@ -362,6 +374,7 @@ extern void blkid_free_dev(blkid_dev dev);
/* probe.c */
extern int blkid_probe_is_tiny(blkid_probe pr);
+extern int blkid_probe_is_cdrom(blkid_probe pr);
extern unsigned char *blkid_probe_get_buffer(blkid_probe pr,
blkid_loff_t off, blkid_loff_t len);
@@ -380,6 +393,9 @@ extern int blkid_probe_set_dimension(blkid_probe pr,
extern blkid_partlist blkid_probe_get_partlist(blkid_probe pr);
+extern int blkid_probe_is_covered_by_pt(blkid_probe pr,
+ blkid_loff_t offset, blkid_loff_t size);
+
extern void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn);
extern int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
struct blkid_prval *vals, int nvals);
diff --git a/shlibs/blkid/src/dev.c b/shlibs/blkid/src/dev.c
index e02f170c..24d989dd 100644
--- a/shlibs/blkid/src/dev.c
+++ b/shlibs/blkid/src/dev.c
@@ -84,7 +84,7 @@ void blkid_debug_dump_dev(blkid_dev dev)
printf(" dev: name = %s\n", dev->bid_name);
printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
- printf(" dev: TIME=\"%ld\"\n", (long)dev->bid_time);
+ printf(" dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
diff --git a/shlibs/blkid/src/devname.c b/shlibs/blkid/src/devname.c
index 5d6da891..64b3432d 100644
--- a/shlibs/blkid/src/devname.c
+++ b/shlibs/blkid/src/devname.c
@@ -20,7 +20,6 @@
#include <unistd.h>
#endif
#include <stdlib.h>
-#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#if HAVE_SYS_TYPES_H
diff --git a/shlibs/blkid/src/devno.c b/shlibs/blkid/src/devno.c
index 284f8733..1d389ac6 100644
--- a/shlibs/blkid/src/devno.c
+++ b/shlibs/blkid/src/devno.c
@@ -16,7 +16,6 @@
#include <unistd.h>
#endif
#include <stdlib.h>
-#include <string.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -31,6 +30,7 @@
#include <sys/mkdev.h>
#endif
#include <fcntl.h>
+#include <inttypes.h>
#include "blkidP.h"
#include "pathnames.h"
@@ -364,7 +364,7 @@ int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
* - dirname ../../block/sda/sda1 = ../../block/sda
* - basename ../../block/sda = sda
*/
- linklen = readlink(path, linkpath, sizeof(linkpath));
+ linklen = readlink(path, linkpath, sizeof(linkpath) - 1);
if (linklen < 0)
goto err;
linkpath[linklen] = '\0';
@@ -452,6 +452,68 @@ int blkid_driver_has_major(const char *drvname, int major)
return match;
}
+static char *mk_devno_attribute_path(char *buf, size_t buflen,
+ dev_t devno, const char *attr)
+{
+ int len = snprintf(buf, buflen, "/sys/dev/block/%d:%d/%s",
+ major(devno), minor(devno), attr);
+
+ if (len < 0 || len + 1 > buflen)
+ return NULL;
+
+ return buf;
+}
+
+int blkid_devno_has_attribute(dev_t devno, const char *attribute)
+{
+ char path[PATH_MAX];
+ struct stat info;
+
+ if (!mk_devno_attribute_path(path, sizeof(path), devno, attribute))
+ return 0;
+
+ if (stat(path, &info) == 0)
+ return 1;
+
+ return 0;
+}
+
+int blkid_devno_get_u64_attribute(dev_t devno, const char *attribute, uint64_t *result)
+{
+ FILE *f;
+ char path[PATH_MAX];
+ int rc = 0;
+
+ if (!mk_devno_attribute_path(path, sizeof(path), devno, attribute))
+ return -1;
+
+ f = fopen(path, "r");
+ if (f) {
+ rc = fscanf(f, "%" SCNu64, result);
+ fclose(f);
+ }
+
+ return rc == 1 ? 0 : -1;
+}
+
+int blkid_devno_get_s64_attribute(dev_t devno, const char *attribute, int64_t *result)
+{
+ FILE *f;
+ char path[PATH_MAX];
+ int rc = 0;
+
+ if (!mk_devno_attribute_path(path, sizeof(path), devno, attribute))
+ return -1;
+
+ f = fopen(path, "r");
+ if (f) {
+ rc = fscanf(f, "%" SCNd64, result);
+ fclose(f);
+ }
+
+ return rc == 1 ? 0 : -1;
+}
+
#ifdef TEST_PROGRAM
int main(int argc, char** argv)
{
diff --git a/shlibs/blkid/src/getsize.c b/shlibs/blkid/src/getsize.c
index 10ba7ecf..2ba8bc65 100644
--- a/shlibs/blkid/src/getsize.c
+++ b/shlibs/blkid/src/getsize.c
@@ -2,6 +2,7 @@
* getsize.c --- get the size of a partition.
*
* Copyright (C) 1995, 1995 Theodore Ts'o.
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the
@@ -9,199 +10,26 @@
* %End-Header%
*/
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-
-/* include this before sys/queues.h! */
-#include "blkidP.h"
-
#include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-#if HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
-
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96) /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
+#include <sys/types.h>
-static int valid_offset(int fd, blkid_loff_t offset)
-{
- char ch;
-
- if (blkid_llseek(fd, offset, 0) < 0)
- return 0;
- if (read(fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
+#include "blkdev.h"
+#include "blkidP.h"
-/*
- * Returns the number of bytes in a partition
+/**
+ * blkid_get_dev_size:
+ * @fd: file descriptor
+ *
+ * Returns: size (in bytes) of the block device or size of the regular file or 0.
*/
blkid_loff_t blkid_get_dev_size(int fd)
{
- int valid_blkgetsize64 = 1;
-#ifdef __linux__
- struct utsname ut;
-#endif
- unsigned long long size64;
- unsigned long size;
- blkid_loff_t high, low;
-#ifdef FDGETPRM
- struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- int part = -1;
- struct disklabel lab;
- struct partition *pp;
- char ch;
- struct stat st;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && (size64 << 9 > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return (blkid_loff_t) size64 << 9;
- }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
- if ((uname(&ut) == 0) &&
- ((ut.release[0] == '2') && (ut.release[1] == '.') &&
- (ut.release[2] < '6') && (ut.release[3] == '.')))
- valid_blkgetsize64 = 0;
-#endif
- if (valid_blkgetsize64 &&
- ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
- if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
- && ((size64) > 0xFFFFFFFF))
- return 0; /* EFBIG */
- return size64;
- }
-#endif
-
-#ifdef BLKGETSIZE
- if (ioctl(fd, BLKGETSIZE, &size) >= 0)
- return (blkid_loff_t)size << 9;
-#endif
-
-/* tested on FreeBSD 6.1-RELEASE i386 */
-#ifdef DIOCGMEDIASIZE
- if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0)
- return (off_t)size64;
-#endif /* DIOCGMEDIASIZE */
-
-#ifdef FDGETPRM
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
- return (blkid_loff_t)this_floppy.size << 9;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
- /*
- * This code works for FreeBSD 4.11 i386, except for the full device
- * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
- * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
- * above however.
- *
- * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
- * character) devices, so we need to check for S_ISCHR, too.
- */
- if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
- part = st.st_rdev & 7;
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size)
- return pp->p_size << 9;
- }
-#endif /* HAVE_SYS_DISKLABEL_H */
- {
-#ifdef HAVE_FSTAT64
- struct stat64 st;
- if (fstat64(fd, &st) == 0)
-#else
- struct stat st;
- if (fstat(fd, &st) == 0)
-#endif
- if (S_ISREG(st.st_mode))
- return st.st_size;
- }
-
+ unsigned long long bytes;
- /*
- * OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the best way. So do binary search to
- * find the size of the partition.
- */
- low = 0;
- for (high = 1024; valid_offset(fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const blkid_loff_t mid = (low + high) / 2;
+ if (blkdev_get_size(fd, &bytes))
+ return 0;
- if (valid_offset(fd, mid))
- low = mid;
- else
- high = mid;
- }
- return low + 1;
+ return bytes;
}
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
- long long bytes;
- int fd;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n"
- "Determine the size of a device\n", argv[0]);
- return 1;
- }
-
- if ((fd = open(argv[1], O_RDONLY)) < 0)
- perror(argv[0]);
-
- bytes = blkid_get_dev_size(fd);
- printf("Device %s has %Ld 1k blocks.\n", argv[1],
- (unsigned long long) bytes >> 10);
-
- return 0;
-}
-#endif
diff --git a/shlibs/blkid/src/partitions/Makefile.am b/shlibs/blkid/src/partitions/Makefile.am
index 6af2022e..f617389d 100644
--- a/shlibs/blkid/src/partitions/Makefile.am
+++ b/shlibs/blkid/src/partitions/Makefile.am
@@ -18,4 +18,5 @@ libblkid_partitions_la_SOURCES = partitions.c \
dos.c \
dos.h \
minix.c \
+ ultrix.c \
gpt.c
diff --git a/shlibs/blkid/src/partitions/bsd.c b/shlibs/blkid/src/partitions/bsd.c
index 9d0d7e5e..ee15ad2f 100644
--- a/shlibs/blkid/src/partitions/bsd.c
+++ b/shlibs/blkid/src/partitions/bsd.c
@@ -164,6 +164,7 @@ static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag)
le16_to_cpu(l->d_npartitions) - BSD_MAXPARTITIONS));
for (i = 0, p = l->d_partitions; i < nparts; i++, p++) {
+ blkid_partition par;
uint32_t start, size;
/* TODO: in fdisk-mode returns all non-zero (p_size) partitions */
@@ -180,8 +181,11 @@ static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag)
continue;
}
- if (!blkid_partlist_add_partition(ls, tab, p->p_fstype, start, size))
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, p->p_fstype);
}
return 0;
diff --git a/shlibs/blkid/src/partitions/dos.c b/shlibs/blkid/src/partitions/dos.c
index ec2ca1eb..7c95b8be 100644
--- a/shlibs/blkid/src/partitions/dos.c
+++ b/shlibs/blkid/src/partitions/dos.c
@@ -75,6 +75,7 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
/* Parse data partition */
for (p = p0, i = 0; i < 4; i++, p++) {
uint32_t abs_start;
+ blkid_partition par;
/* the start is relative to the parental ext.partition */
start = dos_partition_start(p) * ssf;
@@ -93,10 +94,13 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
if (abs_start + size > ex_start + ex_size)
continue;
}
- if (!blkid_partlist_add_partition(ls, tab, p->sys_type,
- abs_start, size))
+
+ par = blkid_partlist_add_partition(ls, tab, abs_start, size);
+ if (!par)
goto err;
+ blkid_partition_set_type(par, p->sys_type);
+ blkid_partition_set_flags(par, p->boot_ind);
ct_nodata = 0;
}
/* The first nested ext.partition should be a link to the next
@@ -194,14 +198,23 @@ static int probe_dos_pt(blkid_probe pr, const struct blkid_idmag *mag)
/* Parse primary partitions */
for (p = p0, i = 0; i < 4; i++, p++) {
+ blkid_partition par;
+
start = dos_partition_start(p) * ssf;
size = dos_partition_size(p) * ssf;
- if (!size)
+ if (!size) {
+ /* Linux kernel ignores empty partitions, but partno for
+ * the empty primary partitions is not reused */
+ blkid_partlist_increment_partno(ls);
continue;
- if (!blkid_partlist_add_partition(ls, tab, p->sys_type,
- start, size))
+ }
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, p->sys_type);
+ blkid_partition_set_flags(par, p->boot_ind);
}
/* Linux uses partition numbers greater than 4
@@ -221,25 +234,26 @@ static int probe_dos_pt(blkid_probe pr, const struct blkid_idmag *mag)
goto err;
}
- /* Parse subtypes (nested partitions) */
- for (p = p0, i = 0; i < 4; i++, p++) {
- int n;
-
- if (!dos_partition_size(p) || is_extended(p))
- continue;
+ /* Parse subtypes (nested partitions) on large disks */
+ if (!blkid_probe_is_tiny(pr)) {
+ for (p = p0, i = 0; i < 4; i++, p++) {
+ int n;
- for (n = 0; n < ARRAY_SIZE(dos_nested); n++) {
- if (dos_nested[n].type != p->sys_type)
+ if (!dos_partition_size(p) || is_extended(p))
continue;
- if (blkid_partitions_do_subprobe(pr,
- blkid_partlist_get_partition(ls, i),
- dos_nested[n].id) == -1)
- goto err;
- break;
+ for (n = 0; n < ARRAY_SIZE(dos_nested); n++) {
+ if (dos_nested[n].type != p->sys_type)
+ continue;
+
+ if (blkid_partitions_do_subprobe(pr,
+ blkid_partlist_get_partition(ls, i),
+ dos_nested[n].id) == -1)
+ goto err;
+ break;
+ }
}
}
-
return 0;
nothing:
diff --git a/shlibs/blkid/src/partitions/gpt.c b/shlibs/blkid/src/partitions/gpt.c
index 2c3a3267..12100e0f 100644
--- a/shlibs/blkid/src/partitions/gpt.c
+++ b/shlibs/blkid/src/partitions/gpt.c
@@ -328,19 +328,21 @@ static int probe_gpt_pt(blkid_probe pr, const struct blkid_idmag *mag)
le64_to_cpu(e->starting_lba) + 1ULL;
/* 00000000-0000-0000-0000-000000000000 entry */
- if (!guidcmp(e->partition_type_guid, GPT_UNUSED_ENTRY_GUID))
+ if (!guidcmp(e->partition_type_guid, GPT_UNUSED_ENTRY_GUID)) {
+ blkid_partlist_increment_partno(ls);
continue;
-
+ }
/* the partition has to inside usable range */
if (start < fu || start + size - 1 > lu) {
DBG(DEBUG_LOWPROBE, printf(
"GPT entry[%d] overflows usable area - ignore\n",
i));
+ blkid_partlist_increment_partno(ls);
continue;
}
- par = blkid_partlist_add_partition(ls, tab, 0,
- start * ssf, size * ssf);
+ par = blkid_partlist_add_partition(ls, tab,
+ start * ssf, size * ssf);
if (!par)
goto err;
@@ -353,6 +355,8 @@ static int probe_gpt_pt(blkid_probe pr, const struct blkid_idmag *mag)
blkid_partition_set_type_uuid(par,
(const unsigned char *) &e->partition_type_guid);
+
+ blkid_partition_set_flags(par, e->attributes);
}
return 0;
diff --git a/shlibs/blkid/src/partitions/mac.c b/shlibs/blkid/src/partitions/mac.c
index 7f4a30b0..538b2727 100644
--- a/shlibs/blkid/src/partitions/mac.c
+++ b/shlibs/blkid/src/partitions/mac.c
@@ -144,7 +144,7 @@ static int probe_mac_pt(blkid_probe pr, const struct blkid_idmag *mag)
start = be32_to_cpu(p->start_block) * ssf;
size = be32_to_cpu(p->block_count) * ssf;
- par = blkid_partlist_add_partition(ls, tab, 0, start, size);
+ par = blkid_partlist_add_partition(ls, tab, start, size);
if (!par)
goto err;
diff --git a/shlibs/blkid/src/partitions/minix.c b/shlibs/blkid/src/partitions/minix.c
index e2f9140f..0887d1a3 100644
--- a/shlibs/blkid/src/partitions/minix.c
+++ b/shlibs/blkid/src/partitions/minix.c
@@ -58,6 +58,7 @@ static int probe_minix_pt(blkid_probe pr, const struct blkid_idmag *mag)
for (i = 0; i < MINIX_MAXPARTITIONS; i++, p++) {
uint32_t start, size;
+ blkid_partition par;
if (p->sys_type != BLKID_MINIX_PARTITION)
continue;
@@ -72,9 +73,12 @@ static int probe_minix_pt(blkid_probe pr, const struct blkid_idmag *mag)
continue;
}
- if (!blkid_partlist_add_partition(ls, tab,
- p->sys_type, start, size))
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, p->sys_type);
+ blkid_partition_set_flags(par, p->boot_ind);
}
return 0;
diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c
index e8d03113..c670cc18 100644
--- a/shlibs/blkid/src/partitions/partitions.c
+++ b/shlibs/blkid/src/partitions/partitions.c
@@ -27,12 +27,22 @@
* @short_description: partitions tables detection and parsing
*
* This chain supports binary and NAME=value interfaces, but complete PT
- * description is provided by binary interface only.
+ * description is provided by binary interface only. The libblkid prober is
+ * compatible with kernel partition tables parser. The parser does not return
+ * empty (size=0) partitions or special hidden partitions.
*
* NAME=value interface, supported tags:
*
* @PTTYPE: partition table type (dos, gpt, etc.).
*
+ * @PART_ENTRY_NAME: partition name (gpt and mac only)
+ *
+ * @PART_ENTRY_UUID: partition UUID (gpt only)
+ *
+ * @PART_ENTRY_TYPE: partition type, 0xNN (e.g 0x82) or type UUID (gpt only) or type string (mac)
+ *
+ * @PART_ENTRY_FLAGS: partition flags (e.g. boot_ind) or attributes (e.g. gpt attributes)
+ *
* Example:
*
* <informalexample>
@@ -104,6 +114,7 @@ static const struct blkid_idinfo *idinfos[] =
&dos_pt_idinfo,
&gpt_pt_idinfo,
&mac_pt_idinfo,
+ &ultrix_pt_idinfo,
&bsd_pt_idinfo,
&unixware_pt_idinfo,
&solaris_x86_pt_idinfo,
@@ -152,6 +163,8 @@ struct blkid_struct_partition {
int type; /* partition type */
char typestr[37]; /* partition type string (GPT and Mac) */
+ unsigned long long flags; /* partition flags / attributes */
+
int partno; /* partition number */
char uuid[37]; /* UUID (when supported by PT), e.g GPT */
unsigned char name[128]; /* Partition in UTF8 name (when supporte by PT), e.g. Mac */
@@ -171,6 +184,8 @@ struct blkid_struct_partlist {
struct list_head l_tabs; /* list of partition tables */
};
+static int blkid_partitions_probe_partition(blkid_probe pr);
+
/**
* blkid_probe_enable_partitions:
* @pr: probe
@@ -263,9 +278,6 @@ int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[])
* use more blkid_partlist objects in the same time you have to create
* more blkid_probe handlers (see blkid_new_probe()).
*
- * TODO: add blkid_ref() and blkid_unref() to allows to use blkid_partlist
- * independently on libblkid probing stuff.
- *
* Returns: list of partitions, or NULL in case of error.
*/
blkid_partlist blkid_probe_get_partitions(blkid_probe pr)
@@ -412,13 +424,13 @@ static blkid_partition new_partition(blkid_partlist ls, blkid_parttable tab)
ref_parttable(tab);
par->tab = tab;
- par->partno = ls->next_partno++;
+ par->partno = blkid_partlist_increment_partno(ls);
return par;
}
blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
- blkid_parttable tab, int type,
+ blkid_parttable tab,
blkid_loff_t start, blkid_loff_t size)
{
blkid_partition par = new_partition(ls, tab);
@@ -426,17 +438,13 @@ blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
if (!par)
return NULL;
- par->type = type;
par->start = start;
par->size = size;
DBG(DEBUG_LOWPROBE,
- printf("parts: add partition (%p type=0x%x, "
- "start=%llu, size=%llu, table=%p)\n",
- par, par->type,
- (unsigned long long) par->start,
- (unsigned long long) par->size,
- tab));
+ printf("parts: add partition (%p start=%llu, size=%llu, table=%p)\n",
+ par, (unsigned long long) par->start,
+ (unsigned long long) par->size, tab));
return par;
}
@@ -449,6 +457,11 @@ int blkid_partlist_set_partno(blkid_partlist ls, int partno)
return 0;
}
+int blkid_partlist_increment_partno(blkid_partlist ls)
+{
+ return ls ? ls->next_partno++ : -1;
+}
+
/* allows to set "parent" for the next nested partition */
int blkid_partlist_set_parent(blkid_partlist ls, blkid_partition par)
{
@@ -557,7 +570,7 @@ nothing:
*/
static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
{
- int i = 0;
+ int i = 0, rc = 1;
if (!pr || chn->idx < -1)
return -1;
@@ -566,6 +579,9 @@ static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
if (chn->binary)
partitions_init_data(pr, chn);
+ if (pr->prob_flags & BLKID_PARTS_IGNORE_PT)
+ goto details_only;
+
DBG(DEBUG_LOWPROBE,
printf("--> starting probing loop [PARTS idx=%d]\n",
chn->idx));
@@ -588,18 +604,35 @@ static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
name = idinfos[i]->name;
/* all checks passed */
- blkid_probe_set_value(pr, "PTTYPE",
- (unsigned char *) name, strlen(name) + 1);
-
+ if (!chn->binary)
+ blkid_probe_set_value(pr, "PTTYPE",
+ (unsigned char *) name,
+ strlen(name) + 1);
DBG(DEBUG_LOWPROBE,
printf("<-- leaving probing loop (type=%s) [PARTS idx=%d]\n",
name, chn->idx));
- return 0;
+ rc = 0;
+ break;
}
- DBG(DEBUG_LOWPROBE,
- printf("<-- leaving probing loop (failed) [PARTS idx=%d]\n",
- chn->idx));
- return 1;
+
+ if (rc == 1) {
+ DBG(DEBUG_LOWPROBE,
+ printf("<-- leaving probing loop (failed) [PARTS idx=%d]\n",
+ chn->idx));
+ }
+
+details_only:
+ /*
+ * Gather PART_ENTRY_* values if the current device is a partition.
+ */
+ if (!chn->binary &&
+ (blkid_partitions_get_flags(pr) & BLKID_PARTS_ENTRY_DETAILS)) {
+
+ if (!blkid_partitions_probe_partition(pr))
+ rc = 0;
+ }
+
+ return rc;
}
/* Probe for nested partition table within the parental partition */
@@ -652,6 +685,165 @@ int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent,
return rc;
}
+static int blkid_partitions_probe_partition(blkid_probe pr)
+{
+ int rc = 1;
+ blkid_probe disk_pr = NULL;
+ blkid_partlist ls;
+ blkid_partition par;
+ dev_t devno, disk_devno;
+ char *disk_path = NULL;
+
+ devno = blkid_probe_get_devno(pr);
+ if (!devno)
+ goto nothing;
+
+ disk_devno = blkid_probe_get_wholedisk_devno(pr);
+ if (!disk_devno)
+ goto nothing;
+
+ if (devno == disk_devno)
+ goto nothing; /* this is not a partition */
+
+ disk_path = blkid_devno_to_devname(disk_devno);
+ if (!disk_path)
+ goto nothing;
+
+ DBG(DEBUG_LOWPROBE, printf(
+ "parts: %d:%d: starting whole-disk probing: %s\n",
+ major(devno), minor(devno), disk_path));
+
+ /* create a new prober for the disk */
+ disk_pr = blkid_new_probe_from_filename(disk_path);
+ if (!disk_pr)
+ goto nothing;
+
+ /* parse PT */
+ ls = blkid_probe_get_partitions(disk_pr);
+ if (!ls)
+ goto nothing;
+
+ par = blkid_partlist_devno_to_partition(ls, devno);
+ if (par) {
+ const char *v;
+ blkid_parttable tab = blkid_partition_get_table(par);
+
+ if (tab) {
+ v = blkid_parttable_get_type(tab);
+ if (v)
+ blkid_probe_set_value(pr, "PART_ENTRY_SCHEME",
+ (unsigned char *) v, strlen(v) + 1);
+ }
+
+ v = blkid_partition_get_name(par);
+ if (v)
+ blkid_probe_set_value(pr, "PART_ENTRY_NAME",
+ (unsigned char *) v, strlen(v) + 1);
+
+ v = blkid_partition_get_uuid(par);
+ if (v)
+ blkid_probe_set_value(pr, "PART_ENTRY_UUID",
+ (unsigned char *) v, strlen(v) + 1);
+
+ /* type */
+ v = blkid_partition_get_type_string(par);
+ if (v)
+ blkid_probe_set_value(pr, "PART_ENTRY_TYPE",
+ (unsigned char *) v, strlen(v) + 1);
+ else
+ blkid_probe_sprintf_value(pr, "PART_ENTRY_TYPE",
+ "0x%x", blkid_partition_get_type(par));
+
+ if (blkid_partition_get_flags(par))
+ blkid_probe_sprintf_value(pr, "PART_ENTRY_FLAGS",
+ "0x%llx", blkid_partition_get_flags(par));
+
+ blkid_probe_sprintf_value(pr, "PART_ENTRY_NUMBER",
+ "%d", blkid_partition_get_partno(par));
+ }
+ rc = 0;
+nothing:
+ blkid_free_probe(disk_pr);
+ free(disk_path);
+ return rc;
+}
+
+/*
+ * This function is compatible with blkid_probe_get_partitions(), but the
+ * result is not stored in @pr and all probing is independent on the
+ * status of @pr. It's possible to call this function from arbitrary
+ * place without a care about @pr.
+ */
+static blkid_partlist blkid_probe_get_independent_partlist(blkid_probe pr)
+{
+
+ blkid_partlist ls = NULL, org_ls = NULL;
+ struct blkid_chain *chn = &pr->chains[BLKID_CHAIN_PARTS];
+ struct blkid_prval vals[BLKID_NVALS_PARTS];
+ int nvals = BLKID_NVALS_PARTS;
+ int idx;
+
+ /* save old results */
+ nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
+ idx = chn->idx;
+ if (chn->data) {
+ org_ls = chn->data;
+ chn->data = NULL;
+ }
+
+ ls = blkid_probe_get_partitions(pr);
+
+ /* restore original results */
+ chn->data = org_ls;
+ chn->idx = idx;
+
+ blkid_probe_chain_reset_vals(pr, chn);
+ blkid_probe_append_vals(pr, vals, nvals);
+
+ return ls;
+}
+
+/*
+ * Returns 1 if the device is whole-disk and the area specified by @offset and
+ * @size is covered by any partition.
+ */
+int blkid_probe_is_covered_by_pt(blkid_probe pr,
+ blkid_loff_t offset, blkid_loff_t size)
+{
+ blkid_partlist ls = NULL;
+ blkid_loff_t start, end;
+ int nparts, i, rc = 0;
+
+ DBG(DEBUG_LOWPROBE, printf(
+ "=> checking if off=%jd size=%jd covered by PT\n",
+ offset, size));
+
+ ls = blkid_probe_get_independent_partlist(pr);
+ if (!ls)
+ goto done;
+
+ nparts = blkid_partlist_numof_partitions(ls);
+ if (!nparts)
+ goto done;
+
+ end = (offset + size) >> 9;
+ start = offset >> 9;
+
+ for (i = 0; i < nparts; i++) {
+ blkid_partition par = &ls->parts[i];
+
+ if (start >= par->start && end <= par->start + par->size) {
+ rc = 1;
+ break;
+ }
+ }
+done:
+ partitions_free_data(pr, (void *)ls);
+
+ DBG(DEBUG_LOWPROBE, printf("<= %s covered by PT\n", rc ? "IS" : "NOT"));
+ return rc;
+}
+
/**
* blkid_known_pttype:
* @pttype: partiton name
@@ -685,17 +877,31 @@ int blkid_partlist_numof_partitions(blkid_partlist ls)
}
/**
+ * blkid_partlist_get_table:
+ *
+ * Returns top-level partition table or NULL of there is not a partition table
+ * on the device.
+ */
+blkid_parttable blkid_partlist_get_table(blkid_partlist ls)
+{
+ if (!ls || list_empty(&ls->l_tabs))
+ return NULL;
+
+ return list_entry(ls->l_tabs.next,
+ struct blkid_struct_parttable, t_tabs);
+}
+
+
+/**
* blkid_partlist_get_partition:
* @ls: partitions list
* @n: partition number in range 0..N, where 'N' is blkid_partlist_numof_partitions().
*
* It's possible that the list of partitions is *empty*, but there is a valid
* partition table on the disk. This happen when on-disk details about
- * partitions are unknown, but we are able to detect partition table magic
- * string only. The nice example is AIX. If your question is: "Is there any
- * partition table?", use:
+ * partitions are unknown or the partition table is empty.
*
- * blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL);
+ * See also blkid_partlist_get_table().
*
* Returns: partition object or NULL in case or error.
*/
@@ -708,6 +914,53 @@ blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
}
/**
+ * blkid_partlist_devno_to_partition:
+ * @ls: partitions list
+ * @devno: requested partition
+ *
+ * This function tries to get start and size for @devno from sysfs and
+ * returns a partition from @ls which matches with the values from sysfs.
+ *
+ * This funtion is necessary when you want to make a relation between an entry
+ * in the partition table (@ls) and block devices in your system.
+ *
+ * Returns: partition object or NULL in case or error.
+ */
+blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno)
+{
+ uint64_t start, size;
+ int i;
+
+ if (blkid_devno_get_u64_attribute(devno, "start", &start))
+ return NULL;
+ if (blkid_devno_get_u64_attribute(devno, "size", &size))
+ return NULL;
+
+ for (i = 0; i < ls->nparts; i++) {
+ blkid_partition par = &ls->parts[i];
+
+ if (blkid_partition_get_start(par) == start &&
+ blkid_partition_get_size(par) == size)
+ return par;
+
+ /* exception for extended dos partitions */
+ if (blkid_partition_get_start(par) == start &&
+ blkid_partition_is_extended(par) && size <= 1024)
+ return par;
+
+ }
+ return NULL;
+}
+
+int blkid_partition_set_type(blkid_partition par, int type)
+{
+ if (!par)
+ return -1;
+ par->type = type;
+ return 0;
+}
+
+/**
* blkid_parttable_get_type:
* @tab: partition table
*
@@ -1031,3 +1284,23 @@ const char *blkid_partition_get_type_string(blkid_partition par)
return par && *par->typestr ? par->typestr : NULL;
}
+
+int blkid_partition_set_flags(blkid_partition par, unsigned long long flags)
+{
+ if (!par)
+ return -1;
+ par->flags = flags;
+ return 0;
+}
+
+/**
+ * blkid_partition_get_flags
+ * @par: partition
+ *
+ * Returns: partition flags (or attributes for gpt).
+ */
+unsigned long long blkid_partition_get_flags(blkid_partition par)
+{
+ return par ? par->flags : 0;
+}
+
diff --git a/shlibs/blkid/src/partitions/partitions.h b/shlibs/blkid/src/partitions/partitions.h
index e017768a..c4ccd3b6 100644
--- a/shlibs/blkid/src/partitions/partitions.h
+++ b/shlibs/blkid/src/partitions/partitions.h
@@ -10,10 +10,12 @@ extern blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls,
const char *type, blkid_loff_t offset);
extern blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
- blkid_parttable tab, int type,
+ blkid_parttable tab,
blkid_loff_t start, blkid_loff_t size);
extern int blkid_partlist_set_partno(blkid_partlist ls, int partno);
+extern int blkid_partlist_increment_partno(blkid_partlist ls);
+
extern blkid_partition blkid_partlist_get_parent(blkid_partlist ls);
extern int blkid_partitions_do_subprobe(blkid_probe pr,
@@ -32,12 +34,16 @@ extern int blkid_partition_set_utf8name(blkid_partition par,
extern int blkid_partition_set_uuid(blkid_partition par,
const unsigned char *uuid);
+extern int blkid_partition_set_type(blkid_partition par, int type);
+
extern int blkid_partition_set_type_string(blkid_partition par,
const unsigned char *type, size_t len);
extern int blkid_partition_set_type_uuid(blkid_partition par,
const unsigned char *uuid);
+extern int blkid_partition_set_flags(blkid_partition par, unsigned long long flags);
+
/*
* partition probers
*/
@@ -51,5 +57,6 @@ extern const struct blkid_idinfo mac_pt_idinfo;
extern const struct blkid_idinfo dos_pt_idinfo;
extern const struct blkid_idinfo minix_pt_idinfo;
extern const struct blkid_idinfo gpt_pt_idinfo;
+extern const struct blkid_idinfo ultrix_pt_idinfo;
#endif /* BLKID_PARTITIONS_H */
diff --git a/shlibs/blkid/src/partitions/sgi.c b/shlibs/blkid/src/partitions/sgi.c
index c1094b78..945ead54 100644
--- a/shlibs/blkid/src/partitions/sgi.c
+++ b/shlibs/blkid/src/partitions/sgi.c
@@ -123,13 +123,18 @@ static int probe_sgi_pt(blkid_probe pr, const struct blkid_idmag *mag)
uint32_t size = be32_to_cpu(p->num_blocks);
uint32_t start = be32_to_cpu(p->first_block);
uint32_t type = be32_to_cpu(p->type);
+ blkid_partition par;
if (size == 0 || type == SGI_TYPE_VOLULME ||
- type == SGI_TYPE_VOLHDR)
+ type == SGI_TYPE_VOLHDR) {
+ blkid_partlist_increment_partno(ls);
continue;
-
- if (!blkid_partlist_add_partition(ls, tab, type, start, size))
+ }
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, type);
}
return 0;
diff --git a/shlibs/blkid/src/partitions/solaris_x86.c b/shlibs/blkid/src/partitions/solaris_x86.c
index fe39a103..ce102bd8 100644
--- a/shlibs/blkid/src/partitions/solaris_x86.c
+++ b/shlibs/blkid/src/partitions/solaris_x86.c
@@ -100,6 +100,7 @@ static int probe_solaris_pt(blkid_probe pr, const struct blkid_idmag *mag)
uint32_t start = le32_to_cpu(p->s_start);
uint32_t size = le32_to_cpu(p->s_size);
+ blkid_partition par;
if (size == 0 || le16_to_cpu(p->s_tag) == SOLARIS_TAG_WHOLEDISK)
continue;
@@ -116,9 +117,12 @@ static int probe_solaris_pt(blkid_probe pr, const struct blkid_idmag *mag)
continue;
}
- if (!blkid_partlist_add_partition(ls, tab,
- le16_to_cpu(p->s_tag), start, size))
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, le16_to_cpu(p->s_tag));
+ blkid_partition_set_flags(par, le16_to_cpu(p->s_flag));
}
return 0;
diff --git a/shlibs/blkid/src/partitions/sun.c b/shlibs/blkid/src/partitions/sun.c
index 4ff000f3..dffab24c 100644
--- a/shlibs/blkid/src/partitions/sun.c
+++ b/shlibs/blkid/src/partitions/sun.c
@@ -32,7 +32,7 @@ struct sun_disklabel {
uint16_t nparts; /* num of partitions */
struct sun_info { /* partition information */
- uint16_t id;
+ uint16_t id; /* tag */
uint16_t flags;
} __attribute__ ((packed)) infos[8];
@@ -84,12 +84,11 @@ static int probe_sun_pt(blkid_probe pr, const struct blkid_idmag *mag)
{
struct sun_disklabel *l;
struct sun_partition *p;
- struct sun_info *infos = NULL;
blkid_parttable tab = NULL;
blkid_partlist ls;
uint16_t nparts;
blkid_loff_t spc;
- int i;
+ int i, use_vtoc;
l = (struct sun_disklabel *) blkid_probe_get_sector(pr, 0);
if (!l)
@@ -113,34 +112,54 @@ static int probe_sun_pt(blkid_probe pr, const struct blkid_idmag *mag)
if (!tab)
goto err;
- /* default number of partitions */
- nparts = SUN_MAXPARTITIONS;
-
/* sectors per cylinder (partition offset is in cylinders...) */
spc = be16_to_cpu(l->ntrks) * be16_to_cpu(l->nsect);
- if ((be32_to_cpu(l->vtoc.sanity) == SUN_VTOC_SANITY) &&
- (be32_to_cpu(l->vtoc.version) == SUN_VTOC_VERSION) &&
- (be16_to_cpu(l->vtoc.nparts) <= SUN_MAXPARTITIONS)) {
+ DBG(DEBUG_LOWPROBE,
+ printf("Sun VTOC sanity=%u version=%u nparts=%u\n",
+ be32_to_cpu(l->vtoc.sanity),
+ be32_to_cpu(l->vtoc.version),
+ be16_to_cpu(l->vtoc.nparts)));
- nparts = be16_to_cpu(l->vtoc.nparts);
- infos = l->vtoc.infos; /* for partition type */
- }
+ /* Check to see if we can use the VTOC table */
+ use_vtoc = ((be32_to_cpu(l->vtoc.sanity) == SUN_VTOC_SANITY) &&
+ (be32_to_cpu(l->vtoc.version) == SUN_VTOC_VERSION) &&
+ (be16_to_cpu(l->vtoc.nparts) <= SUN_MAXPARTITIONS));
+
+ /* Use 8 partition entries if not specified in validated VTOC */
+ nparts = use_vtoc ? be16_to_cpu(l->vtoc.nparts) : SUN_MAXPARTITIONS;
+
+ /*
+ * So that old Linux-Sun partitions continue to work,
+ * alow the VTOC to be used under the additional condition ...
+ */
+ use_vtoc = use_vtoc || !(l->vtoc.sanity || l->vtoc.version || l->vtoc.nparts);
for (i = 0, p = l->partitions; i < nparts; i++, p++) {
- blkid_loff_t start;
- blkid_loff_t size;
- uint16_t type = infos ? be16_to_cpu(infos[i].id) : 0;
+ blkid_loff_t start, size;
+ uint16_t type = 0, flags = 0;
+ blkid_partition par;
start = be32_to_cpu(p->start_cylinder) * spc;
size = be32_to_cpu(p->num_sectors);
+ if (use_vtoc) {
+ type = be16_to_cpu(l->vtoc.infos[i].id);
+ flags = be16_to_cpu(l->vtoc.infos[i].flags);
+ }
- if (type == SUN_TAG_WHOLEDISK || !size)
+ if (type == SUN_TAG_WHOLEDISK || !size) {
+ blkid_partlist_increment_partno(ls);
continue;
-
- if (!blkid_partlist_add_partition(ls, tab, type, start, size))
+ }
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ if (type)
+ blkid_partition_set_type(par, type);
+ if (flags)
+ blkid_partition_set_flags(par, flags);
}
return 0;
diff --git a/shlibs/blkid/src/partitions/ultrix.c b/shlibs/blkid/src/partitions/ultrix.c
new file mode 100644
index 00000000..cc848d0a
--- /dev/null
+++ b/shlibs/blkid/src/partitions/ultrix.c
@@ -0,0 +1,88 @@
+/*
+ * uktrix partition parsing code
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "partitions.h"
+
+#define ULTRIX_MAXPARTITIONS 8
+#define ULTRIX_MAGIC 0x032957
+
+/* sector with partition table */
+#define ULTRIX_SECTOR ((16384 - sizeof(struct ultrix_disklabel)) >> 9)
+/* position of partition table within ULTRIX_SECTOR */
+#define ULTRIX_OFFSET (512 - sizeof(struct ultrix_disklabel))
+
+struct ultrix_disklabel {
+ int32_t pt_magic; /* magic no. indicating part. info exits */
+ int32_t pt_valid; /* set by driver if pt is current */
+ struct pt_info {
+ int32_t pi_nblocks; /* no. of sectors */
+ uint32_t pi_blkoff; /* block offset for start */
+ } pt_part[ULTRIX_MAXPARTITIONS];
+} __attribute__((packed));
+
+
+static int probe_ultrix_pt(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ unsigned char *data;
+ struct ultrix_disklabel *l;
+ blkid_parttable tab = NULL;
+ blkid_partlist ls;
+ int i;
+
+ data = blkid_probe_get_sector(pr, ULTRIX_SECTOR);
+ if (!data)
+ goto nothing;
+
+ l = (struct ultrix_disklabel *) (data + ULTRIX_OFFSET);
+
+ if (l->pt_magic != ULTRIX_MAGIC || l->pt_valid != 1)
+ goto nothing;
+
+ if (blkid_partitions_need_typeonly(pr))
+ /* caller does not ask for details about partitions */
+ return 0;
+
+ ls = blkid_probe_get_partlist(pr);
+ if (!ls)
+ goto err;
+
+ tab = blkid_partlist_new_parttable(ls, "ultrix", 0);
+ if (!tab)
+ goto err;
+
+ for (i = 0; i < ULTRIX_MAXPARTITIONS; i++) {
+ if (!l->pt_part[i].pi_nblocks)
+ blkid_partlist_increment_partno(ls);
+ else {
+ if (!blkid_partlist_add_partition(ls, tab,
+ l->pt_part[i].pi_blkoff,
+ l->pt_part[i].pi_nblocks))
+ goto err;
+ }
+ }
+
+ return 0;
+nothing:
+ return 1;
+err:
+ return -1;
+}
+
+const struct blkid_idinfo ultrix_pt_idinfo =
+{
+ .name = "ultrix",
+ .probefunc = probe_ultrix_pt,
+ .magics = BLKID_NONE_MAGIC
+};
+
diff --git a/shlibs/blkid/src/partitions/unixware.c b/shlibs/blkid/src/partitions/unixware.c
index 62dba764..ac11a46d 100644
--- a/shlibs/blkid/src/partitions/unixware.c
+++ b/shlibs/blkid/src/partitions/unixware.c
@@ -132,6 +132,7 @@ static int probe_unixware_pt(blkid_probe pr, const struct blkid_idmag *mag)
uint32_t start, size;
uint16_t tag, flg;
+ blkid_partition par;
tag = le16_to_cpu(p->s_label);
flg = le16_to_cpu(p->s_flags);
@@ -151,8 +152,12 @@ static int probe_unixware_pt(blkid_probe pr, const struct blkid_idmag *mag)
continue;
}
- if (!blkid_partlist_add_partition(ls, tab, tag, start, size))
+ par = blkid_partlist_add_partition(ls, tab, start, size);
+ if (!par)
goto err;
+
+ blkid_partition_set_type(par, tag);
+ blkid_partition_set_flags(par, flg);
}
return 0;
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index e7845816..89c59504 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -16,7 +16,7 @@
* the selected (see blkid_probe_set_device()) device.
*
* The probing routines are grouped together into separate chains. Currently,
- * the librray provides superblocks, partitions and topology chains.
+ * the library provides superblocks, partitions and topology chains.
*
* The probing routines is possible to filter (enable/disable) by type (e.g.
* fstype "vfat" or partype "gpt") or by usage flags (e.g. BLKID_USAGE_RAID).
@@ -35,6 +35,20 @@
* 2. The binary interfaces. These interfaces return data in the native formats.
* The interface is always specific to the probing chain.
*
+ * Note that the previous probing result (binary or NAME=value) is always
+ * zeroized when a chain probing function is called. For example
+ *
+ * <informalexample>
+ * <programlisting>
+ * blkid_probe_enable_partitions(pr, TRUE);
+ * blkid_probe_enable_superblocks(pr, FALSE);
+ *
+ * blkid_do_safeprobe(pr);
+ * </programlisting>
+ * </informalexample>
+ *
+ * overwrites the previous probing result for the partitions chain, the superblocks
+ * result is not modified.
*/
/**
@@ -77,6 +91,9 @@
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
+#ifdef HAVE_LINUX_CDROM_H
+#include <linux/cdrom.h>
+#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -287,21 +304,33 @@ struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
{
- int rc;
+ int rc, org_prob_flags;
+ struct blkid_chain *org_chn;
if (!pr || !chn)
return NULL;
+ /* save the current setting -- the binary API has to be completely
+ * independent on the current probing status
+ */
+ org_chn = pr->cur_chain;
+ org_prob_flags = pr->prob_flags;
+
pr->cur_chain = chn;
+ pr->prob_flags = 0;
chn->binary = TRUE;
blkid_probe_chain_reset_position(chn);
rc = chn->driver->probe(pr, chn);
chn->binary = FALSE;
- pr->cur_chain = NULL;
blkid_probe_chain_reset_position(chn);
+ /* restore the original setting
+ */
+ pr->cur_chain = org_chn;
+ pr->prob_flags = org_prob_flags;
+
if (rc != 0)
return NULL;
@@ -545,6 +574,14 @@ int blkid_probe_is_tiny(blkid_probe pr)
return pr && (pr->flags & BLKID_TINY_DEV);
}
+/*
+ * CDROMs may fail when probed for RAID (last sector problem)
+ */
+int blkid_probe_is_cdrom(blkid_probe pr)
+{
+ return pr && (pr->flags & BLKID_CDROM_DEV);
+}
+
/**
* blkid_probe_set_device:
* @pr: probe
@@ -560,6 +597,8 @@ int blkid_probe_is_tiny(blkid_probe pr)
int blkid_probe_set_device(blkid_probe pr, int fd,
blkid_loff_t off, blkid_loff_t size)
{
+ struct stat sb;
+
if (!pr)
return -1;
@@ -569,6 +608,8 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
close(pr->fd);
pr->flags &= ~BLKID_PRIVATE_FD;
+ pr->flags &= ~BLKID_TINY_DEV;
+ pr->flags &= ~BLKID_CDROM_DEV;
pr->fd = fd;
pr->off = off;
pr->size = 0;
@@ -580,26 +621,27 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
/* Disable read-ahead */
posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
#endif
+ if (fstat(fd, &sb))
+ goto err;
+
+ pr->mode = sb.st_mode;
+ if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
+ pr->devno = sb.st_rdev;
+
if (size)
pr->size = size;
else {
- struct stat sb;
-
- if (fstat(fd, &sb))
- goto err;
-
- pr->mode = sb.st_mode;
-
- if (S_ISBLK(sb.st_mode))
- blkdev_get_size(fd, (unsigned long long *) &pr->size);
- else if (S_ISCHR(sb.st_mode))
+ if (S_ISBLK(sb.st_mode)) {
+ if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
+ DBG(DEBUG_LOWPROBE, printf(
+ "failed to get device size\n"));
+ goto err;
+ }
+ } else if (S_ISCHR(sb.st_mode))
pr->size = 1; /* UBI devices are char... */
else if (S_ISREG(sb.st_mode))
pr->size = sb.st_size; /* regular file */
- if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
- pr->devno = sb.st_rdev;
-
if (pr->off > pr->size)
goto err;
@@ -608,12 +650,16 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
pr->size -= pr->off;
}
- DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
+ DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n",
pr->off, pr->size));
- if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode))
+ if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
pr->flags |= BLKID_TINY_DEV;
+#ifdef CDROM_GET_CAPABILITY
+ if (S_ISBLK(sb.st_mode) && ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0)
+ pr->flags |= BLKID_CDROM_DEV;
+#endif
return 0;
err:
DBG(DEBUG_LOWPROBE,
@@ -659,6 +705,22 @@ int blkid_probe_set_dimension(blkid_probe pr,
return 0;
}
+static inline void blkid_probe_start(blkid_probe pr)
+{
+ if (pr) {
+ pr->cur_chain = NULL;
+ pr->prob_flags = 0;
+ }
+}
+
+static inline void blkid_probe_end(blkid_probe pr)
+{
+ if (pr) {
+ pr->cur_chain = NULL;
+ pr->prob_flags = 0;
+ }
+}
+
/**
* blkid_do_probe:
* @pr: prober
@@ -710,23 +772,28 @@ int blkid_do_probe(blkid_probe pr)
do {
struct blkid_chain *chn = pr->cur_chain;
- if (!chn)
+ if (!chn) {
+ blkid_probe_start(pr);
chn = pr->cur_chain = &pr->chains[0];
-
+ }
/* we go to the next chain only when the previous probing
* result was nothing (rc == 1) and when the current chain is
* disabled or we are at end of the current chain (chain->idx +
- * 1 == sizeof chain)
+ * 1 == sizeof chain) or the current chain bailed out right at
+ * the start (chain->idx == -1)
*/
else if (rc == 1 && (chn->enabled == FALSE ||
- chn->idx + 1 == chn->driver->nidinfos)) {
+ chn->idx + 1 == chn->driver->nidinfos ||
+ chn->idx == -1)) {
int idx = chn->driver->id + 1;
if (idx < BLKID_NCHAINS)
chn = pr->cur_chain = &pr->chains[idx];
- else
+ else {
+ blkid_probe_end(pr);
return 1; /* all chains already probed */
+ }
}
chn->binary = FALSE; /* for sure... */
@@ -758,7 +825,9 @@ int blkid_do_probe(blkid_probe pr)
*
* Note about suberblocks chain -- the function does not check for filesystems
* when a RAID signature is detected. The function also does not check for
- * collision between RAIDs. The first detected RAID is returned.
+ * collision between RAIDs. The first detected RAID is returned. The function
+ * checks for collision between partition table and RAID signature -- it's
+ * recommended to enable partitions chain together with superblocks chain.
*
* Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
* detected and -1 on case of error.
@@ -770,6 +839,8 @@ int blkid_do_safeprobe(blkid_probe pr)
if (!pr)
return -1;
+ blkid_probe_start(pr);
+
for (i = 0; i < BLKID_NCHAINS; i++) {
struct blkid_chain *chn;
@@ -797,7 +868,7 @@ int blkid_do_safeprobe(blkid_probe pr)
}
done:
- pr->cur_chain = NULL;
+ blkid_probe_end(pr);
if (rc < 0)
return rc;
return count ? 0 : 1;
@@ -822,6 +893,8 @@ int blkid_do_fullprobe(blkid_probe pr)
if (!pr)
return -1;
+ blkid_probe_start(pr);
+
for (i = 0; i < BLKID_NCHAINS; i++) {
int rc;
struct blkid_chain *chn;
@@ -850,7 +923,7 @@ int blkid_do_fullprobe(blkid_probe pr)
}
done:
- pr->cur_chain = NULL;
+ blkid_probe_end(pr);
if (rc < 0)
return rc;
return count ? 0 : 1;
@@ -960,21 +1033,60 @@ int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
*/
dev_t blkid_probe_get_devno(blkid_probe pr)
{
- if (!pr->devno) {
- struct stat sb;
+ return pr->devno;
+}
+
+/**
+ * blkid_probe_get_wholedisk_devno:
+ * @pr: probe
+ *
+ * Returns: device number of the wholedisk, or 0 for regilar files.
+ */
+dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
+{
+ if (!pr->disk_devno) {
+ dev_t devno, disk_devno = 0;
+
+ devno = blkid_probe_get_devno(pr);
+ if (!devno)
+ return 0;
- if (fstat(pr->fd, &sb) == 0 &&
- (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)))
- pr->devno = sb.st_rdev;
+ if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
+ pr->disk_devno = disk_devno;
}
- return pr->devno;
+ return pr->disk_devno;
+}
+
+/**
+ * blkid_probe_is_wholedisk:
+ * @pr: probe
+ *
+ * Returns: 1 if the device is whole-disk or 0.
+ */
+int blkid_probe_is_wholedisk(blkid_probe pr)
+{
+ dev_t devno, disk_devno;
+
+ devno = blkid_probe_get_devno(pr);
+ if (!devno)
+ return 0;
+
+ disk_devno = blkid_probe_get_wholedisk_devno(pr);
+ if (!disk_devno)
+ return 0;
+
+ return devno == disk_devno;
}
/**
* blkid_probe_get_size:
* @pr: probe
*
- * Returns: block device (or file) size in bytes or -1 in case of error.
+ * This function returns size of probing area as defined by blkid_probe_set_device().
+ * If the size of the probing area is unrestricted then this function returns
+ * the real size of device. See also blkid_get_dev_size().
+ *
+ * Returns: size in bytes or -1 in case of error.
*/
blkid_loff_t blkid_probe_get_size(blkid_probe pr)
{
@@ -982,32 +1094,47 @@ blkid_loff_t blkid_probe_get_size(blkid_probe pr)
}
/**
- * blkid_probe_get_sectorsize:
+ * blkid_probe_get_offset:
* @pr: probe
*
+ * This function returns offset of probing area as defined by blkid_probe_set_device().
+ *
+ * Returns: offset in bytes or -1 in case of error.
+ */
+blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
+{
+ return pr ? pr->off : -1;
+}
+
+/**
+ * blkid_probe_get_fd:
+ * @pr: probe
+ *
+ * Returns: file descriptor for assigned device/file.
+ */
+int blkid_probe_get_fd(blkid_probe pr)
+{
+ return pr ? pr->fd : -1;
+}
+
+/**
+ * blkid_probe_get_sectorsize:
+ * @pr: probe or NULL (for NULL returns 512)
+ *
* Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
*/
unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
{
if (!pr)
return DEFAULT_SECTOR_SIZE; /*... and good luck! */
+
if (pr->blkssz)
return pr->blkssz;
- if (!pr->mode) {
- struct stat st;
-
- if (fstat(pr->fd, &st))
- goto fallback;
- pr->mode = st.st_mode;
- }
- if (S_ISBLK(pr->mode)) {
- if (blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz))
- goto fallback;
- return pr->blkssz;
- }
+ if (S_ISBLK(pr->mode) &&
+ blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
+ return pr->blkssz;
-fallback:
pr->blkssz = DEFAULT_SECTOR_SIZE;
return pr->blkssz;
}
diff --git a/shlibs/blkid/src/read.c b/shlibs/blkid/src/read.c
index b5e9cd02..e6aa0836 100644
--- a/shlibs/blkid/src/read.c
+++ b/shlibs/blkid/src/read.c
@@ -49,7 +49,8 @@ static void debug_dump_dev(blkid_dev dev);
*
* The following tags are required for each entry:
* <ID="id"> unique (within this file) ID number of this device
- * <TIME="time"> (ascii time_t) time this entry was last read from disk
+ * <TIME="sec.usec"> (time_t and suseconds_t) time this entry was last
+ * read from disk
* <TYPE="type"> (detected) type of filesystem/data for this partition
*
* The following tags may be present, depending on the device contents
@@ -318,9 +319,12 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
dev->bid_devno = STRTOULL(value, 0, 0);
else if (!strcmp(name, "PRI"))
dev->bid_pri = strtol(value, 0, 0);
- else if (!strcmp(name, "TIME"))
- dev->bid_time = STRTOULL(value, 0, 0);
- else
+ else if (!strcmp(name, "TIME")) {
+ char *end = NULL;
+ dev->bid_time = STRTOULL(value, &end, 0);
+ if (end && *end == '.')
+ dev->bid_utime = STRTOULL(end + 1, 0, 0);
+ } else
ret = blkid_set_tag(dev, name, value, strlen(value));
DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
@@ -455,7 +459,7 @@ static void debug_dump_dev(blkid_dev dev)
printf(" dev: name = %s\n", dev->bid_name);
printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
- printf(" dev: TIME=\"%lld\"\n", (long long)dev->bid_time);
+ printf(" dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
diff --git a/shlibs/blkid/src/save.c b/shlibs/blkid/src/save.c
index a1583ecc..c04c2242 100644
--- a/shlibs/blkid/src/save.c
+++ b/shlibs/blkid/src/save.c
@@ -37,9 +37,11 @@ static int save_dev(blkid_dev dev, FILE *file)
printf("device %s, type %s\n", dev->bid_name, dev->bid_type ?
dev->bid_type : "(null)"));
- fprintf(file,
- "<device DEVNO=\"0x%04lx\" TIME=\"%ld\"",
- (unsigned long) dev->bid_devno, (long) dev->bid_time);
+ fprintf(file, "<device DEVNO=\"0x%04lx\" TIME=\"%ld.%ld\"",
+ (unsigned long) dev->bid_devno,
+ (long) dev->bid_time,
+ (long) dev->bid_utime);
+
if (dev->bid_pri)
fprintf(file, " PRI=\"%d\"", dev->bid_pri);
list_for_each(p, &dev->bid_tags) {
diff --git a/shlibs/blkid/src/superblocks/adaptec_raid.c b/shlibs/blkid/src/superblocks/adaptec_raid.c
index c6b175b4..73b146c6 100644
--- a/shlibs/blkid/src/superblocks/adaptec_raid.c
+++ b/shlibs/blkid/src/superblocks/adaptec_raid.c
@@ -94,7 +94,9 @@ static int probe_adraid(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
if (blkid_probe_sprintf_version(pr, "%u", ad->resver) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(ad->b0idcode),
+ (unsigned char *) &ad->b0idcode))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/befs.c b/shlibs/blkid/src/superblocks/befs.c
index b341402a..c238bae3 100644
--- a/shlibs/blkid/src/superblocks/befs.c
+++ b/shlibs/blkid/src/superblocks/befs.c
@@ -123,13 +123,13 @@ static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
bi = (struct befs_inode *) blkid_probe_get_buffer(pr,
- (FS32_TO_CPU(bs->root_dir.allocation_group, fs_le)
- << FS32_TO_CPU(bs->ag_shift, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le))
- + (FS16_TO_CPU(bs->root_dir.start, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le)),
- FS16_TO_CPU(bs->root_dir.len, fs_le)
- << FS32_TO_CPU(bs->block_shift, fs_le));
+ ((blkid_loff_t)FS32_TO_CPU(bs->root_dir.allocation_group, fs_le)
+ << FS32_TO_CPU(bs->ag_shift, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le))
+ + ((blkid_loff_t)FS16_TO_CPU(bs->root_dir.start, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le)),
+ (blkid_loff_t)FS16_TO_CPU(bs->root_dir.len, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le));
if (!bi)
return -1;
diff --git a/shlibs/blkid/src/superblocks/ddf_raid.c b/shlibs/blkid/src/superblocks/ddf_raid.c
index 89bd92c7..a48735d2 100644
--- a/shlibs/blkid/src/superblocks/ddf_raid.c
+++ b/shlibs/blkid/src/superblocks/ddf_raid.c
@@ -32,12 +32,13 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
int i;
struct ddf_header *ddf = NULL;
char version[DDF_REV_LENGTH + 1];
+ uint64_t off;
if (pr->size < 0x30000)
return -1;
for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
- uint64_t off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
+ off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
ddf = (struct ddf_header *) blkid_probe_get_buffer(pr,
off,
@@ -61,6 +62,10 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
if (blkid_probe_set_version(pr, version) != 0)
return -1;
+ if (blkid_probe_set_magic(pr, off,
+ sizeof(ddf->signature),
+ (unsigned char *) ddf->signature))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/drbd.c b/shlibs/blkid/src/superblocks/drbd.c
index a56486e9..3490948d 100644
--- a/shlibs/blkid/src/superblocks/drbd.c
+++ b/shlibs/blkid/src/superblocks/drbd.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
+#include <stddef.h>
#include "superblocks.h"
@@ -75,9 +76,9 @@ static int probe_drbd(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
md = (struct md_on_disk_08 *)
- blkid_probe_get_buffer(pr,
- off,
- sizeof(struct md_on_disk_08));
+ blkid_probe_get_buffer(pr,
+ off,
+ sizeof(struct md_on_disk_08));
if (!md)
return -1;
@@ -90,10 +91,16 @@ static int probe_drbd(blkid_probe pr, const struct blkid_idmag *mag)
*/
blkid_probe_sprintf_uuid(pr,
(unsigned char *) &md->device_uuid, sizeof(md->device_uuid),
- "0x%" PRIx64, be64_to_cpu(md->device_uuid));
+ "%" PRIx64, be64_to_cpu(md->device_uuid));
blkid_probe_set_version(pr, "v08");
+ if (blkid_probe_set_magic(pr,
+ off + offsetof(struct md_on_disk_08, magic),
+ sizeof(md->magic),
+ (unsigned char *) &md->magic))
+ return -1;
+
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/highpoint_raid.c b/shlibs/blkid/src/superblocks/highpoint_raid.c
index 111ceb2c..98343c41 100644
--- a/shlibs/blkid/src/superblocks/highpoint_raid.c
+++ b/shlibs/blkid/src/superblocks/highpoint_raid.c
@@ -41,6 +41,9 @@ static int probe_highpoint45x(blkid_probe pr, const struct blkid_idmag *mag)
magic = le32_to_cpu(hpt->magic);
if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
return -1;
+ if (blkid_probe_set_magic(pr, off, sizeof(hpt->magic),
+ (unsigned char *) &hpt->magic))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/isw_raid.c b/shlibs/blkid/src/superblocks/isw_raid.c
index 0f4869fd..5149c38a 100644
--- a/shlibs/blkid/src/superblocks/isw_raid.c
+++ b/shlibs/blkid/src/superblocks/isw_raid.c
@@ -46,7 +46,9 @@ static int probe_iswraid(blkid_probe pr, const struct blkid_idmag *mag)
if (blkid_probe_sprintf_version(pr, "%6s",
&isw->sig[sizeof(ISW_SIGNATURE)-1]) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(isw->sig),
+ (unsigned char *) isw->sig))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/jmicron_raid.c b/shlibs/blkid/src/superblocks/jmicron_raid.c
index 70e0e1c6..24430bf9 100644
--- a/shlibs/blkid/src/superblocks/jmicron_raid.c
+++ b/shlibs/blkid/src/superblocks/jmicron_raid.c
@@ -45,7 +45,9 @@ static int probe_jmraid(blkid_probe pr, const struct blkid_idmag *mag)
if (blkid_probe_sprintf_version(pr, "%u.%u",
jm->major_version, jm->minor_version) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(jm->signature),
+ (unsigned char *) jm->signature))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/linux_raid.c b/shlibs/blkid/src/superblocks/linux_raid.c
index 0fba6348..6f823f15 100644
--- a/shlibs/blkid/src/superblocks/linux_raid.c
+++ b/shlibs/blkid/src/superblocks/linux_raid.c
@@ -95,7 +95,9 @@ static int probe_raid0(blkid_probe pr, off_t off)
if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(mdp0->md_magic),
+ (unsigned char *) &mdp0->md_magic))
+ return -1;
return 0;
}
@@ -118,7 +120,9 @@ static int probe_raid1(blkid_probe pr, off_t off)
if (blkid_probe_set_label(pr, mdp1->set_name,
sizeof(mdp1->set_name)) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(mdp1->magic),
+ (unsigned char *) &mdp1->magic))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/lsi_raid.c b/shlibs/blkid/src/superblocks/lsi_raid.c
index 6baaaa47..3010eb6b 100644
--- a/shlibs/blkid/src/superblocks/lsi_raid.c
+++ b/shlibs/blkid/src/superblocks/lsi_raid.c
@@ -41,7 +41,9 @@ static int probe_lsiraid(blkid_probe pr, const struct blkid_idmag *mag)
if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(lsi->sig),
+ (unsigned char *) lsi->sig))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/luks.c b/shlibs/blkid/src/superblocks/luks.c
index 0af85b53..f716e31c 100644
--- a/shlibs/blkid/src/superblocks/luks.c
+++ b/shlibs/blkid/src/superblocks/luks.c
@@ -49,7 +49,7 @@ static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag)
blkid_probe_strncpy_uuid(pr, (unsigned char *) header->uuid,
sizeof(header->uuid));
- blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(header->version));
+ blkid_probe_sprintf_version(pr, "%u", be16_to_cpu(header->version));
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/minix.c b/shlibs/blkid/src/superblocks/minix.c
index 7b314abc..3290c275 100644
--- a/shlibs/blkid/src/superblocks/minix.c
+++ b/shlibs/blkid/src/superblocks/minix.c
@@ -9,6 +9,7 @@
* GNU Lesser General Public License.
*/
+#include <string.h>
#include "superblocks.h"
struct minix_super_block {
@@ -45,6 +46,7 @@ struct minix3_super_block {
static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
{
+ unsigned char *ext;
int version;
/* for more details see magic strings below */
@@ -88,6 +90,14 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
}
+ /* unfortunately, some parts of ext3 is sometimes possible to
+ * interpreted as minix superblock. So check for extN magic
+ * string. (For extN magic string and offsets see ext.c.)
+ */
+ ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
+ if (ext && memcmp(ext, "\123\357", 2) == 0)
+ return -1;
+
blkid_probe_sprintf_version(pr, "%d", version);
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/nvidia_raid.c b/shlibs/blkid/src/superblocks/nvidia_raid.c
index 8ce7f12a..e75bec84 100644
--- a/shlibs/blkid/src/superblocks/nvidia_raid.c
+++ b/shlibs/blkid/src/superblocks/nvidia_raid.c
@@ -43,10 +43,11 @@ static int probe_nvraid(blkid_probe pr, const struct blkid_idmag *mag)
if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
return -1;
-
if (blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(nv->version)) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr, off, sizeof(nv->vendor),
+ (unsigned char *) nv->vendor))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/promise_raid.c b/shlibs/blkid/src/superblocks/promise_raid.c
index 94a64469..1cc70e65 100644
--- a/shlibs/blkid/src/superblocks/promise_raid.c
+++ b/shlibs/blkid/src/superblocks/promise_raid.c
@@ -47,8 +47,13 @@ static int probe_pdcraid(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
if (memcmp(pdc->sig, PDC_SIGNATURE,
- sizeof(PDC_SIGNATURE) - 1) == 0)
+ sizeof(PDC_SIGNATURE) - 1) == 0) {
+
+ if (blkid_probe_set_magic(pr, off, sizeof(pdc->sig),
+ (unsigned char *) pdc->sig))
+ return -1;
return 0;
+ }
}
return -1;
}
diff --git a/shlibs/blkid/src/superblocks/silicon_raid.c b/shlibs/blkid/src/superblocks/silicon_raid.c
index 2144e505..11277ad6 100644
--- a/shlibs/blkid/src/superblocks/silicon_raid.c
+++ b/shlibs/blkid/src/superblocks/silicon_raid.c
@@ -15,6 +15,7 @@
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
+#include <stddef.h>
#include "superblocks.h"
@@ -63,7 +64,11 @@ static int probe_silraid(blkid_probe pr, const struct blkid_idmag *mag)
le16_to_cpu(sil->major_ver),
le16_to_cpu(sil->minor_ver)) != 0)
return -1;
-
+ if (blkid_probe_set_magic(pr,
+ off + offsetof(struct silicon_metadata, magic),
+ sizeof(sil->magic),
+ (unsigned char *) &sil->magic))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c
index 56b334d0..1d952737 100644
--- a/shlibs/blkid/src/superblocks/superblocks.c
+++ b/shlibs/blkid/src/superblocks/superblocks.c
@@ -71,6 +71,7 @@
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn);
+static void superblocks_free(blkid_probe pr, void *data);
static int blkid_probe_set_usage(blkid_probe pr, int usage);
@@ -154,9 +155,23 @@ const struct blkid_chaindrv superblocks_drv = {
.nidinfos = ARRAY_SIZE(idinfos),
.has_fltr = TRUE,
.probe = superblocks_probe,
- .safeprobe = superblocks_safeprobe
+ .safeprobe = superblocks_safeprobe,
+ .free_data = superblocks_free
};
+/*
+ * Private chain data
+ *
+ * TODO: export this data by binary interface (see topology.c or partitions.c
+ * for more details) by blkid_probe_get_superblock() or so.
+ */
+struct blkid_struct_superblock {
+ blkid_loff_t magic_off; /* offset of the magic string */
+ int usage;
+};
+
+/* TODO: move to blkid.h */
+typedef struct blkid_struct_superblock *blkid_superblock;
/**
* blkid_probe_enable_superblocks:
@@ -296,6 +311,39 @@ int blkid_known_fstype(const char *fstype)
return 0;
}
+/* init and returns private data */
+static blkid_superblock superblocks_init_data(blkid_probe pr,
+ struct blkid_chain *chn)
+{
+ DBG(DEBUG_LOWPROBE, printf("initialize superblocks binary data\n"));
+
+ if (chn->data)
+ memset(chn->data, 0,
+ sizeof(struct blkid_struct_superblock));
+ else {
+ chn->data = calloc(1,
+ sizeof(struct blkid_struct_superblock));
+ if (!chn->data)
+ return NULL;
+ }
+ return chn->data;
+}
+
+static void superblocks_free(blkid_probe pr, void *data)
+{
+ free(data);
+}
+
+static blkid_superblock superblocks_copy_data(blkid_superblock dest,
+ blkid_superblock src)
+{
+ if (!src || !dest)
+ return NULL;
+
+ memcpy(dest, src, sizeof(struct blkid_struct_superblock));
+ return dest;
+}
+
/*
* The blkid_do_probe() backend.
*/
@@ -315,7 +363,10 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
/* Ignore very very small block devices or regular files (e.g.
* extended partitions). Note that size of the UBI char devices
* is 1 byte */
- return 1;
+ goto nothing;
+
+ if (chn->binary)
+ superblocks_init_data(pr, chn);
i = chn->idx + 1;
@@ -343,6 +394,11 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
blkid_probe_is_tiny(pr))
continue;
+ /* don't probe for RAIDs, swap or journal on floppies or CD/DVDs */
+ if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
+ (blkid_probe_is_tiny(pr) || blkid_probe_is_cdrom(pr)))
+ continue;
+
DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name));
/* try to detect by magic string */
@@ -371,8 +427,10 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
/* final check by probing function */
if (id->probefunc) {
DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n"));
- if (id->probefunc(pr, mag) != 0)
+ if (id->probefunc(pr, mag) != 0) {
+ blkid_probe_chain_reset_vals(pr, chn);
continue;
+ }
}
/* all cheks passed */
@@ -381,21 +439,19 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
(unsigned char *) id->name,
strlen(id->name) + 1);
- if (chn->flags & BLKID_SUBLKS_USAGE)
- blkid_probe_set_usage(pr, id->usage);
+ blkid_probe_set_usage(pr, id->usage);
- if (hasmag && (chn->flags & BLKID_SUBLKS_MAGIC)) {
- blkid_probe_set_value(pr, "SBMAGIC",
- (unsigned char *) mag->magic, mag->len);
- blkid_probe_sprintf_value(pr, "SBMAGIC_OFFSET",
- "%llu", off);
- }
+ if (hasmag)
+ blkid_probe_set_magic(pr, off, mag->len,
+ (unsigned char *) mag->magic);
DBG(DEBUG_LOWPROBE,
printf("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]\n",
id->name, chn->idx));
return 0;
}
+
+nothing:
DBG(DEBUG_LOWPROBE,
printf("<-- leaving probing loop (failed) [SUBLKS idx=%d]\n",
chn->idx));
@@ -416,23 +472,31 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
*/
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
{
+ blkid_superblock sb = NULL;
+ struct blkid_struct_superblock sb_buff;
+
struct blkid_prval vals[BLKID_NVALS_SUBLKS];
int nvals = BLKID_NVALS_SUBLKS;
int idx = -1;
int count = 0;
int intol = 0;
- int rc;
+ int rc, bin_org = chn->binary;
+
+ chn->binary = TRUE;
while ((rc = superblocks_probe(pr, chn)) == 0) {
- if (blkid_probe_is_tiny(pr) && !count)
+ if (blkid_probe_is_tiny(pr) && !count) {
/* floppy or so -- returns the first result. */
+ chn->binary = bin_org;
return 0;
-
+ }
if (!count) {
/* save the first result */
nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
idx = chn->idx;
+ if (chn->data)
+ sb = superblocks_copy_data(&sb_buff, chn->data);
}
count++;
@@ -441,6 +505,9 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
if (!(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
intol++;
}
+
+ chn->binary = bin_org;
+
if (rc < 0)
return rc; /* error */
if (count > 1 && intol) {
@@ -456,11 +523,57 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
/* restore the first result */
blkid_probe_chain_reset_vals(pr, chn);
blkid_probe_append_vals(pr, vals, nvals);
+ if (sb && chn->data)
+ superblocks_copy_data(chn->data, sb);
chn->idx = idx;
+ /*
+ * Check for collisions between RAID and partition table
+ */
+ if (sb && sb->usage == BLKID_USAGE_RAID &&
+ sb->magic_off > pr->size / 2 &&
+ (S_ISREG(pr->mode) || blkid_probe_is_wholedisk(pr)) &&
+ blkid_probe_is_covered_by_pt(pr, sb->magic_off, 0x200)) {
+ /*
+ * Ignore the result if the detected RAID superblock is
+ * within some existing partition (for example RAID on
+ * the last partition).
+ */
+ blkid_probe_chain_reset_vals(pr, chn);
+ return 1;
+ }
+
+ /*
+ * The RAID device could be partitioned. The problem are RAID1 devices
+ * where the partition table is visible from underlaying devices. We
+ * have to ignore such partition tables.
+ */
+ if (sb && sb->usage == BLKID_USAGE_RAID)
+ pr->prob_flags |= BLKID_PARTS_IGNORE_PT;
+
return 0;
}
+int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
+ size_t len, unsigned char *magic)
+{
+ int rc = 0;
+ struct blkid_chain *chn = blkid_probe_get_chain(pr);
+
+ if (chn->flags & BLKID_SUBLKS_MAGIC) {
+ if (magic && len)
+ rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
+ if (!rc && offset)
+ rc = blkid_probe_sprintf_value(pr, "SBMAGIC_OFFSET",
+ "%llu", offset);
+ }
+ if (!rc && chn->data) {
+ blkid_superblock sb = (blkid_superblock) chn->data;
+ sb->magic_off = offset;
+ }
+ return rc;
+}
+
int blkid_probe_set_version(blkid_probe pr, const char *version)
{
struct blkid_chain *chn = blkid_probe_get_chain(pr);
@@ -488,8 +601,17 @@ int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
static int blkid_probe_set_usage(blkid_probe pr, int usage)
{
+ struct blkid_chain *chn = blkid_probe_get_chain(pr);
char *u = NULL;
+ if (chn->data) {
+ blkid_superblock sb = (blkid_superblock) chn->data;
+ sb->usage = usage;
+ }
+
+ if (!(chn->flags & BLKID_SUBLKS_USAGE))
+ return 0;
+
if (usage & BLKID_USAGE_FILESYSTEM)
u = "filesystem";
else if (usage & BLKID_USAGE_RAID)
diff --git a/shlibs/blkid/src/superblocks/superblocks.h b/shlibs/blkid/src/superblocks/superblocks.h
index 12f197e5..b1fa49d5 100644
--- a/shlibs/blkid/src/superblocks/superblocks.h
+++ b/shlibs/blkid/src/superblocks/superblocks.h
@@ -69,6 +69,8 @@ extern const struct blkid_idinfo befs_idinfo;
/*
* superblock functions
*/
+extern int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
+ size_t len, unsigned char *magic);
extern int blkid_probe_set_version(blkid_probe pr, const char *version);
extern int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
diff --git a/shlibs/blkid/src/superblocks/swap.c b/shlibs/blkid/src/superblocks/swap.c
index 8aaa6f31..e2b0db9f 100644
--- a/shlibs/blkid/src/superblocks/swap.c
+++ b/shlibs/blkid/src/superblocks/swap.c
@@ -33,6 +33,8 @@ struct swap_header_v1_2 {
#define PAGESIZE_MIN 0xff6 /* 4086 (arm, i386, ...) */
#define PAGESIZE_MAX 0xfff6 /* 65526 (ia64) */
+#define TOI_MAGIC_STRING "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
+#define TOI_MAGIC_STRLEN (sizeof(TOI_MAGIC_STRING) - 1)
static int swap_set_info(blkid_probe pr, const char *version)
{
@@ -64,9 +66,19 @@ static int swap_set_info(blkid_probe pr, const char *version)
static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
{
+ unsigned char *buf;
+
if (!mag)
return -1;
+ /* TuxOnIce keeps valid swap header at the end of the 1st page */
+ buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
+ if (!buf)
+ return -1;
+
+ if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
+ return 1; /* Ignore swap signature, it's TuxOnIce */
+
if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
/* swap v0 doesn't support LABEL or UUID */
blkid_probe_set_version(pr, "1");
@@ -88,7 +100,7 @@ static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
return swap_set_info(pr, "s2suspend");
if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
return swap_set_info(pr, "ulsuspend");
- if (!memcmp(mag->magic, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", mag->len))
+ if (!memcmp(mag->magic, TOI_MAGIC_STRING, mag->len))
return swap_set_info(pr, "tuxonice");
return -1; /* no signature detected */
@@ -125,26 +137,22 @@ const struct blkid_idinfo swsuspend_idinfo =
.minsz = 10 * 4096, /* 10 pages */
.magics =
{
+ { TOI_MAGIC_STRING, TOI_MAGIC_STRLEN, 0, 0 },
{ "S1SUSPEND", 9, 0, 0xff6 },
{ "S2SUSPEND", 9, 0, 0xff6 },
{ "ULSUSPEND", 9, 0, 0xff6 },
- { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0xff6 },
{ "S1SUSPEND", 9, 0, 0x1ff6 },
{ "S2SUSPEND", 9, 0, 0x1ff6 },
{ "ULSUSPEND", 9, 0, 0x1ff6 },
- { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x1ff6 },
{ "S1SUSPEND", 9, 0, 0x3ff6 },
{ "S2SUSPEND", 9, 0, 0x3ff6 },
{ "ULSUSPEND", 9, 0, 0x3ff6 },
- { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x3ff6 },
{ "S1SUSPEND", 9, 0, 0x7ff6 },
{ "S2SUSPEND", 9, 0, 0x7ff6 },
{ "ULSUSPEND", 9, 0, 0x7ff6 },
- { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x7ff6 },
{ "S1SUSPEND", 9, 0, 0xfff6 },
{ "S2SUSPEND", 9, 0, 0xfff6 },
{ "ULSUSPEND", 9, 0, 0xfff6 },
- { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0xfff6 },
{ NULL }
}
};
diff --git a/shlibs/blkid/src/superblocks/sysv.c b/shlibs/blkid/src/superblocks/sysv.c
index 530e860f..00c8c978 100644
--- a/shlibs/blkid/src/superblocks/sysv.c
+++ b/shlibs/blkid/src/superblocks/sysv.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
+#include <stddef.h>
#include "superblocks.h"
@@ -107,7 +108,18 @@ static int probe_sysv(blkid_probe pr, const struct blkid_idmag *mag)
if (sb->s_magic == cpu_to_le32(0xfd187e20) ||
sb->s_magic == cpu_to_be32(0xfd187e20)) {
- blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname));
+
+ if (blkid_probe_set_label(pr, sb->s_fname,
+ sizeof(sb->s_fname)))
+ return -1;
+
+ if (blkid_probe_set_magic(pr,
+ off + offsetof(struct sysv_super_block,
+ s_magic),
+ sizeof(sb->s_magic),
+ (unsigned char *) &sb->s_magic))
+ return -1;
+
return 0;
}
}
diff --git a/shlibs/blkid/src/superblocks/ufs.c b/shlibs/blkid/src/superblocks/ufs.c
index cdce75ef..05bed145 100644
--- a/shlibs/blkid/src/superblocks/ufs.c
+++ b/shlibs/blkid/src/superblocks/ufs.c
@@ -15,6 +15,7 @@
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
+#include <stddef.h>
#include "superblocks.h"
@@ -205,6 +206,13 @@ found:
} else
blkid_probe_set_version(pr, "1");
+ if (blkid_probe_set_magic(pr,
+ (offsets[i] * 1024) +
+ offsetof(struct ufs_super_block, fs_magic),
+ sizeof(ufs->fs_magic),
+ (unsigned char *) &ufs->fs_magic))
+ return -1;
+
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/via_raid.c b/shlibs/blkid/src/superblocks/via_raid.c
index fc974a70..58650454 100644
--- a/shlibs/blkid/src/superblocks/via_raid.c
+++ b/shlibs/blkid/src/superblocks/via_raid.c
@@ -69,6 +69,10 @@ static int probe_viaraid(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
if (blkid_probe_sprintf_version(pr, "%u", v->version_number) != 0)
return -1;
+ if (blkid_probe_set_magic(pr, off,
+ sizeof(v->signature),
+ (unsigned char *) &v->signature))
+ return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/zfs.c b/shlibs/blkid/src/superblocks/zfs.c
index 0f580262..af5264d4 100644
--- a/shlibs/blkid/src/superblocks/zfs.c
+++ b/shlibs/blkid/src/superblocks/zfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 by Andreas Dilger <adilger@sun.com>
+ * Copyright (C) 2009-2010 by Andreas Dilger <adilger@sun.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
@@ -15,6 +15,10 @@
#include "superblocks.h"
+#define VDEV_LABEL_UBERBLOCK (128 * 1024ULL)
+#define VDEV_LABEL_NVPAIR ( 16 * 1024ULL)
+#define VDEV_LABEL_SIZE (256 * 1024ULL)
+
/* #include <sys/uberblock_impl.h> */
#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */
struct zfs_uberblock {
@@ -23,45 +27,196 @@ struct zfs_uberblock {
uint64_t ub_txg; /* txg of last sync */
uint64_t ub_guid_sum; /* sum of all vdev guids */
uint64_t ub_timestamp; /* UTC time of last sync */
- /*blkptr_t ub_rootbp;*/ /* MOS objset_phys_t */
+ char ub_rootbp; /* MOS objset_phys_t */
} __attribute__((packed));
+#define ZFS_TRIES 64
+#define ZFS_WANT 4
+
+#define DATA_TYPE_UINT64 8
+#define DATA_TYPE_STRING 9
+
+struct nvpair {
+ uint32_t nvp_size;
+ uint32_t nvp_unkown;
+ uint32_t nvp_namelen;
+ char nvp_name[0]; /* aligned to 4 bytes */
+ /* aligned ptr array for string arrays */
+ /* aligned array of data for value */
+};
+
+struct nvstring {
+ uint32_t nvs_type;
+ uint32_t nvs_elem;
+ uint32_t nvs_strlen;
+ unsigned char nvs_string[0];
+};
+
+struct nvuint64 {
+ uint32_t nvu_type;
+ uint32_t nvu_elem;
+ uint64_t nvu_value;
+};
+
+struct nvlist {
+ uint32_t nvl_unknown[3];
+ struct nvpair nvl_nvpair;
+};
+
+#define nvdebug(fmt, ...) do { } while(0)
+/*#define nvdebug(fmt, a...) printf(fmt, ##a)*/
+
+static void zfs_extract_guid_name(blkid_probe pr, loff_t offset)
+{
+ struct nvlist *nvl;
+ struct nvpair *nvp;
+ int left = 4096;
+ int found = 0;
+
+ offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR;
+
+ /* Note that we currently assume that the desired fields are within
+ * the first 4k (left) of the nvlist. This is true for all pools
+ * I've seen, and simplifies this code somewhat, because we don't
+ * have to handle an nvpair crossing a buffer boundary. */
+ nvl = (struct nvlist *)blkid_probe_get_buffer(pr, offset, left);
+ if (nvl == NULL)
+ return;
+
+ nvdebug("zfs_extract: nvlist offset %llu\n", offset);
+
+ nvp = &nvl->nvl_nvpair;
+ while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) {
+ int avail; /* tracks that name/value data fits in nvp_size */
+ int namesize;
+
+ nvp->nvp_size = be32_to_cpu(nvp->nvp_size);
+ nvp->nvp_namelen = be32_to_cpu(nvp->nvp_namelen);
+ avail = nvp->nvp_size - nvp->nvp_namelen - sizeof(*nvp);
+
+ nvdebug("left %u, nvp_size %u\n", left, nvp->nvp_size);
+ if (left < nvp->nvp_size || avail < 0)
+ break;
+
+ namesize = (nvp->nvp_namelen + 3) & ~3;
+
+ nvdebug("nvlist: size %u, namelen %u, name %*s\n",
+ nvp->nvp_size, nvp->nvp_namelen, nvp->nvp_namelen,
+ nvp->nvp_name);
+ if (strncmp(nvp->nvp_name, "name", nvp->nvp_namelen) == 0) {
+ struct nvstring *nvs = (void *)(nvp->nvp_name+namesize);
+
+ nvs->nvs_type = be32_to_cpu(nvs->nvs_type);
+ nvs->nvs_strlen = be32_to_cpu(nvs->nvs_strlen);
+ avail -= nvs->nvs_strlen + sizeof(*nvs);
+ nvdebug("nvstring: type %u string %*s\n", nvs->nvs_type,
+ nvs->nvs_strlen, nvs->nvs_string);
+ if (nvs->nvs_type == DATA_TYPE_STRING && avail >= 0)
+ blkid_probe_set_label(pr, nvs->nvs_string,
+ nvs->nvs_strlen);
+ found++;
+ } else if (strncmp(nvp->nvp_name, "guid",
+ nvp->nvp_namelen) == 0) {
+ struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
+ uint64_t nvu_value;
+
+ memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
+ nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
+ nvu_value = be64_to_cpu(nvu_value);
+ avail -= sizeof(*nvu);
+ nvdebug("nvuint64: type %u value %"PRIu64"\n",
+ nvu->nvu_type, nvu_value);
+ if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
+ blkid_probe_sprintf_value(pr, "UUID_SUB",
+ "%"PRIu64, nvu_value);
+ found++;
+ } else if (strncmp(nvp->nvp_name, "pool_guid",
+ nvp->nvp_namelen) == 0) {
+ struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
+ uint64_t nvu_value;
+
+ memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
+ nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
+ nvu_value = be64_to_cpu(nvu_value);
+ avail -= sizeof(*nvu);
+ nvdebug("nvuint64: type %u value %"PRIu64"\n",
+ nvu->nvu_type, nvu_value);
+ if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
+ blkid_probe_sprintf_uuid(pr, (unsigned char *)
+ &nvu_value,
+ sizeof(nvu_value),
+ "%"PRIu64, nvu_value);
+ found++;
+ }
+ left -= nvp->nvp_size;
+ nvp = (struct nvpair *)((char *)nvp + nvp->nvp_size);
+ }
+}
+
+#define zdebug(fmt, ...) do {} while(0)
+/*#define zdebug(fmt, a...) printf(fmt, ##a)*/
+
+/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas at the start
+ * of the disk, and 2 areas at the end of the disk. Check only some of them...
+ * #4 (@ 132kB) is the first one written on a new filesystem. */
static int probe_zfs(blkid_probe pr, const struct blkid_idmag *mag)
{
+ uint64_t swab_magic = swab64(UBERBLOCK_MAGIC);
struct zfs_uberblock *ub;
int swab_endian;
- uint64_t spa_version;
+ loff_t offset;
+ int tried;
+ int found;
+
+ zdebug("probe_zfs\n");
+ /* Look for at least 4 uberblocks to ensure a positive match */
+ for (tried = found = 0, offset = VDEV_LABEL_UBERBLOCK;
+ tried < ZFS_TRIES && found < ZFS_WANT;
+ tried++, offset += 4096) {
+ /* also try the second uberblock copy */
+ if (tried == (ZFS_TRIES / 2))
+ offset = VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK;
- ub = blkid_probe_get_sb(pr, mag, struct zfs_uberblock);
- if (!ub)
+ ub = (struct zfs_uberblock *)
+ blkid_probe_get_buffer(pr, offset,
+ sizeof(struct zfs_uberblock));
+ if (ub == NULL)
+ return -1;
+
+ if (ub->ub_magic == UBERBLOCK_MAGIC)
+ found++;
+
+ if ((swab_endian = (ub->ub_magic == swab_magic)))
+ found++;
+
+ zdebug("probe_zfs: found %s-endian uberblock at %llu\n",
+ swab_endian ? "big" : "little", offset >> 10);
+ }
+
+ if (found < 4)
return -1;
- swab_endian = (ub->ub_magic == swab64(UBERBLOCK_MAGIC));
- spa_version = swab_endian ? swab64(ub->ub_version) : ub->ub_version;
+ /* If we found the 4th uberblock, then we will have exited from the
+ * scanning loop immediately, and ub will be a valid uberblock. */
+ blkid_probe_sprintf_version(pr, "%" PRIu64, swab_endian ?
+ swab64(ub->ub_version) : ub->ub_version);
+
+ zfs_extract_guid_name(pr, offset);
+
+ if (blkid_probe_set_magic(pr, offset,
+ sizeof(ub->ub_magic),
+ (unsigned char *) &ub->ub_magic))
+ return -1;
- blkid_probe_sprintf_version(pr, "%" PRIu64, spa_version);
-#if 0
- /* read nvpair data for pool name, pool GUID from the MOS, but
- * unfortunately this is more complex than it could be */
- blkid_probe_set_label(pr, pool_name, pool_len));
- blkid_probe_set_uuid(pr, pool_guid);
-#endif
return 0;
}
const struct blkid_idinfo zfs_idinfo =
{
- .name = "zfs",
- .usage = BLKID_USAGE_FILESYSTEM,
+ .name = "zfs_member",
+ .usage = BLKID_USAGE_RAID,
.probefunc = probe_zfs,
.minsz = 64 * 1024 * 1024,
- .magics =
- {
- { .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 8 },
- { .magic = "\x1c\xb1\x07\xb0\xf5\x02\0\0", .len = 8, .kboff = 8 },
- { .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 264 },
- { .magic = "\x0c\xb1\x07\xb0\xf5\x02\0\0", .len = 8, .kboff = 264 },
- { NULL }
- }
+ .magics = BLKID_NONE_MAGIC
};
diff --git a/shlibs/blkid/src/topology/dm.c b/shlibs/blkid/src/topology/dm.c
index 15c0842d..8f33911c 100644
--- a/shlibs/blkid/src/topology/dm.c
+++ b/shlibs/blkid/src/topology/dm.c
@@ -1,6 +1,6 @@
/*
* device-mapper (dm) topology
- * -- this is fallback for old systems where the toplogy information are not
+ * -- this is fallback for old systems where the topology information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
diff --git a/shlibs/blkid/src/topology/evms.c b/shlibs/blkid/src/topology/evms.c
index 7e796915..baab16ed 100644
--- a/shlibs/blkid/src/topology/evms.c
+++ b/shlibs/blkid/src/topology/evms.c
@@ -1,7 +1,7 @@
/*
* Evms topology
- * -- this is fallback for old systems where the toplogy information are not
- * exporte dy sysfs
+ * -- this is fallback for old systems where the toplogy information is not
+ * exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
diff --git a/shlibs/blkid/src/topology/ioctl.c b/shlibs/blkid/src/topology/ioctl.c
index 709b2f45..f18f8568 100644
--- a/shlibs/blkid/src/topology/ioctl.c
+++ b/shlibs/blkid/src/topology/ioctl.c
@@ -26,11 +26,12 @@ static struct topology_val {
long ioc;
- /* function to set probing resut */
- int (*set_result)(blkid_probe, unsigned long);
+ /* functions to set probing result */
+ int (*set_ulong)(blkid_probe, unsigned long);
+ int (*set_int)(blkid_probe, int);
} topology_vals[] = {
- { BLKALIGNOFF, blkid_topology_set_alignment_offset },
+ { BLKALIGNOFF, NULL, blkid_topology_set_alignment_offset },
{ BLKIOMIN, blkid_topology_set_minimum_io_size },
{ BLKIOOPT, blkid_topology_set_optimal_io_size },
{ BLKPBSZGET, blkid_topology_set_physical_sector_size }
@@ -40,23 +41,24 @@ static struct topology_val {
static int probe_ioctl_tp(blkid_probe pr, const struct blkid_idmag *mag)
{
int i;
- int count = 0;
for (i = 0; i < ARRAY_SIZE(topology_vals); i++) {
struct topology_val *val = &topology_vals[i];
+ int rc = 1;
unsigned int data;
- int rc;
if (ioctl(pr->fd, val->ioc, &data) == -1)
goto nothing;
- rc = val->set_result(pr, (unsigned long) data);
+
+ if (val->set_int)
+ rc = val->set_int(pr, (int) data);
+ else
+ rc = val->set_ulong(pr, (unsigned long) data);
if (rc)
goto err;
- count++;
}
- if (count)
- return 0;
+ return 0;
nothing:
return 1;
err:
diff --git a/shlibs/blkid/src/topology/lvm.c b/shlibs/blkid/src/topology/lvm.c
index c760dcbc..54438b0a 100644
--- a/shlibs/blkid/src/topology/lvm.c
+++ b/shlibs/blkid/src/topology/lvm.c
@@ -1,6 +1,6 @@
/*
* lvm topology
- * -- this is fallback for old systems where the toplogy information are not
+ * -- this is fallback for old systems where the topology information is not
* exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
diff --git a/shlibs/blkid/src/topology/md.c b/shlibs/blkid/src/topology/md.c
index 77116163..a761e170 100644
--- a/shlibs/blkid/src/topology/md.c
+++ b/shlibs/blkid/src/topology/md.c
@@ -1,7 +1,7 @@
/*
* Linux Software RAID (md) topology
- * -- this is fallback for old systems where the toplogy information are not
- * exporte dy sysfs
+ * -- this is fallback for old systems where the topology information is not
+ * exported by sysfs
*
* Copyright (C) 2009 Karel Zak <kzak@redhat.com>
*
diff --git a/shlibs/blkid/src/topology/sysfs.c b/shlibs/blkid/src/topology/sysfs.c
index 20c507f1..d04f0a86 100644
--- a/shlibs/blkid/src/topology/sysfs.c
+++ b/shlibs/blkid/src/topology/sysfs.c
@@ -11,7 +11,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <stdint.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -19,78 +19,20 @@
#include "topology.h"
-static unsigned long dev_topology_attribute(const char *attribute,
- dev_t dev, dev_t *primary)
-{
- const char *sysfs_fmt_str = "/sys/dev/block/%d:%d/%s";
- char path[PATH_MAX];
- int len;
- FILE *fp = NULL;
- struct stat info;
- unsigned long result = 0UL;
-
- len = snprintf(path, sizeof(path), sysfs_fmt_str,
- major(dev), minor(dev), attribute);
- if (len < 0 || len + 1 > sizeof(path))
- goto err;
-
- /*
- * check if the desired sysfs attribute exists
- * - if not: either the kernel doesn't have topology support or the
- * device could be a partition
- */
- if (stat(path, &info) < 0) {
- if (!*primary &&
- blkid_devno_to_wholedisk(dev, NULL, 0, primary))
- goto err;
-
- /* get attribute from partition's primary device */
- len = snprintf(path, sizeof(path), sysfs_fmt_str,
- major(*primary), minor(*primary), attribute);
- if (len < 0 || len + 1 > sizeof(path))
- goto err;
- }
-
- fp = fopen(path, "r");
- if (!fp) {
- DBG(DEBUG_LOWPROBE, printf(
- "topology: %s: fopen failed, errno=%d\n", path, errno));
- goto err;
- }
-
- if (fscanf(fp, "%lu", &result) != 1) {
- DBG(DEBUG_LOWPROBE, printf(
- "topology: %s: unexpected file format\n", path));
- goto err;
- }
-
- fclose(fp);
-
- DBG(DEBUG_LOWPROBE,
- printf("topology: attribute %s = %lu\n", attribute, result));
-
- return result;
-err:
- if (fp)
- fclose(fp);
- DBG(DEBUG_LOWPROBE,
- printf("topology: failed to read %s attribute\n", attribute));
- return 0;
-}
-
/*
* Sysfs topology values (since 2.6.31, May 2009).
*/
static struct topology_val {
- /* /sys/dev/block/<maj>:<min>/NAME */
- const char *sysfs_name;
+ /* /sys/dev/block/<maj>:<min>/<ATTR> */
+ const char *attr;
- /* function to set probing resut */
- int (*set_result)(blkid_probe, unsigned long);
+ /* functions to set probing resut */
+ int (*set_ulong)(blkid_probe, unsigned long);
+ int (*set_int)(blkid_probe, int);
} topology_vals[] = {
- { "alignment_offset", blkid_topology_set_alignment_offset },
+ { "alignment_offset", NULL, blkid_topology_set_alignment_offset },
{ "queue/minimum_io_size", blkid_topology_set_minimum_io_size },
{ "queue/optimal_io_size", blkid_topology_set_optimal_io_size },
{ "queue/physical_block_size", blkid_topology_set_physical_sector_size },
@@ -99,7 +41,7 @@ static struct topology_val {
static int probe_sysfs_tp(blkid_probe pr, const struct blkid_idmag *mag)
{
dev_t dev, pri_dev = 0;
- int i, rc = 0, count = 0;
+ int i, count = 0;
dev = blkid_probe_get_devno(pr);
if (!dev)
@@ -107,17 +49,34 @@ static int probe_sysfs_tp(blkid_probe pr, const struct blkid_idmag *mag)
for (i = 0; i < ARRAY_SIZE(topology_vals); i++) {
struct topology_val *val = &topology_vals[i];
- unsigned long data;
-
- /*
- * Don't bother reporting any of the topology information
- * if it's zero.
- */
- data = dev_topology_attribute(val->sysfs_name, dev, &pri_dev);
- if (!data)
- continue;
+ dev_t attr_dev = dev;
+ int rc = 1;
+
+ if (!blkid_devno_has_attribute(dev, val->attr)) {
+ /* get attribute from partition's primary device */
+ if (!pri_dev &&
+ blkid_devno_to_wholedisk(dev, NULL, 0, &pri_dev))
+ continue;
+ attr_dev = pri_dev;
+ }
+
+ if (val->set_ulong) {
+ uint64_t data = 0;
+
+ if (blkid_devno_get_u64_attribute(attr_dev,
+ val->attr, &data))
+ continue;
+ rc = val->set_ulong(pr, (unsigned long) data);
+
+ } else if (val->set_int) {
+ int64_t data = 0;
+
+ if (blkid_devno_get_s64_attribute(attr_dev,
+ val->attr, &data))
+ continue;
+ rc = val->set_int(pr, (int) data);
+ }
- rc = val->set_result(pr, data);
if (rc)
goto err;
count++;
diff --git a/shlibs/blkid/src/topology/topology.c b/shlibs/blkid/src/topology/topology.c
index db97c5fb..f39f49fb 100644
--- a/shlibs/blkid/src/topology/topology.c
+++ b/shlibs/blkid/src/topology/topology.c
@@ -17,9 +17,9 @@
/**
* SECTION:topology
* @title: Topology information
- * @short_description: block device tolology information.
+ * @short_description: block device topology information.
*
- * The tolology chain provides details about Linux block devices, for more
+ * The topology chain provides details about Linux block devices, for more
* information see:
*
* Linux kernel Documentation/ABI/testing/sysfs-block
@@ -40,12 +40,16 @@
* @OPTIMAL_IO_SIZE: usually the stripe width for RAID or zero. For RAID arrays
* it is usually the stripe width or the internal track size.
*
- * @ALIGNMENT_OFFSET: indicates how many bytes the beginning o the device is
+ * @ALIGNMENT_OFFSET: indicates how many bytes the beginning of the device is
* offset from the disk's natural alignment.
*
+ * The NAME=value tags are not defined when the corresponding topology value
+ * is zero. The MINIMUM_IO_SIZE should be always defined if kernel provides
+ * topology information.
+ *
* Binary interface:
*
- * blkid_probe_get_tolology()
+ * blkid_probe_get_topology()
*
* blkid_topology_get_'VALUENAME'()
*/
@@ -122,13 +126,13 @@ int blkid_probe_enable_topology(blkid_probe pr, int enable)
*
* WARNING: the returned object will be overwritten by the next
* blkid_probe_get_topology() call for the same @pr. If you want to
- * use more blkid_tolopogy objects in the same time you have to create
+ * use more blkid_topopogy objects in the same time you have to create
* more blkid_probe handlers (see blkid_new_probe()).
*
* TODO: add blkid_ref() and blkid_unref() to allows to use blkid_topology
* independently on libblkid probing stuff.
*
- * Returns: blkid_tolopogy, or NULL in case of error.
+ * Returns: blkid_topopogy, or NULL in case of error.
*/
blkid_topology blkid_probe_get_topology(blkid_probe pr)
{
@@ -214,6 +218,8 @@ static int topology_set_value(blkid_probe pr, const char *name,
if (!chn)
return -1;
+ if (!data)
+ return 0; /* ignore zeros */
if (chn->binary) {
unsigned long *v =
@@ -225,7 +231,7 @@ static int topology_set_value(blkid_probe pr, const char *name,
}
/* the topology info is complete when we have at least "minimum_io_size" which
- * is provides by all blkid topology drivers */
+ * is provided by all blkid topology drivers */
static int topology_is_complete(blkid_probe pr)
{
struct blkid_chain *chn = blkid_probe_get_chain(pr);
@@ -242,12 +248,26 @@ static int topology_is_complete(blkid_probe pr)
return __blkid_probe_lookup_value(pr, "MINIMUM_IO_SIZE") ? TRUE : FALSE;
}
-int blkid_topology_set_alignment_offset(blkid_probe pr, unsigned long val)
+int blkid_topology_set_alignment_offset(blkid_probe pr, int val)
{
+ unsigned long xval;
+
+ /* Welcome to Hell. The kernel is able to return -1 as an
+ * alignment_offset if no compatible sizes and alignments
+ * exist for stacked devices.
+ *
+ * There is no way how libblkid caller can respond to the value -1, so
+ * we will hide this corner case...
+ *
+ * (TODO: maybe we can export an extra boolean value 'misaligned' rather
+ * then complete hide this problem.)
+ */
+ xval = val < 0 ? 0 : val;
+
return topology_set_value(pr,
"ALIGNMENT_OFFSET",
offsetof(struct blkid_struct_topology, alignment_offset),
- val);
+ xval);
}
int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val)
@@ -267,7 +287,7 @@ int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val)
}
/* BLKSSZGET is provided on all systems since 2.3.3 -- so we don't have to
- * waste time with sysfs or or.
+ * waste time with sysfs.
*/
static int topology_set_logical_sector_size(blkid_probe pr)
{
diff --git a/shlibs/blkid/src/topology/topology.h b/shlibs/blkid/src/topology/topology.h
index d4879204..b7429d90 100644
--- a/shlibs/blkid/src/topology/topology.h
+++ b/shlibs/blkid/src/topology/topology.h
@@ -3,7 +3,7 @@
#include "blkidP.h"
-extern int blkid_topology_set_alignment_offset(blkid_probe pr, unsigned long val);
+extern int blkid_topology_set_alignment_offset(blkid_probe pr, int val);
extern int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val);
extern int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val);
extern int blkid_topology_set_physical_sector_size(blkid_probe pr, unsigned long val);
diff --git a/shlibs/blkid/src/verify.c b/shlibs/blkid/src/verify.c
index 27360260..a0cb3fea 100644
--- a/shlibs/blkid/src/verify.c
+++ b/shlibs/blkid/src/verify.c
@@ -11,6 +11,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
+#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -73,19 +74,34 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
return NULL;
}
- if ((now >= dev->bid_time) &&
- (st.st_mtime <= dev->bid_time) &&
- ((diff < BLKID_PROBE_MIN) ||
- (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
- diff < BLKID_PROBE_INTERVAL)))
+ if (now >= dev->bid_time &&
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ (st.st_mtime < dev->bid_time ||
+ (st.st_mtime == dev->bid_time &&
+ st.st_mtim.tv_nsec / 1000 <= dev->bid_utime)) &&
+#else
+ st.st_mtime <= dev->bid_time &&
+#endif
+ (diff < BLKID_PROBE_MIN ||
+ (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
+ diff < BLKID_PROBE_INTERVAL)))
return dev;
+#ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
DBG(DEBUG_PROBE,
printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
"time since last check %lu)\n",
dev->bid_name, (unsigned long)dev->bid_time,
(unsigned long)st.st_mtime, (unsigned long)diff));
-
+#else
+ DBG(DEBUG_PROBE,
+ printf("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\n\t"
+ "time since last check %lu)\n",
+ dev->bid_name,
+ (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime,
+ (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000,
+ (unsigned long)diff));
+#endif
if (!cache->probe) {
cache->probe = blkid_new_probe();
@@ -156,8 +172,16 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
found_type:
if (dev) {
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ struct timeval tv;
+ if (!gettimeofday(&tv, NULL)) {
+ dev->bid_time = tv.tv_sec;
+ dev->bid_utime = tv.tv_usec;
+ } else
+#endif
+ dev->bid_time = time(0);
+
dev->bid_devno = st.st_rdev;
- dev->bid_time = time(0);
dev->bid_flags |= BLKID_BID_FL_VERIFIED;
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
diff --git a/shlibs/uuid/src/gen_uuid.c b/shlibs/uuid/src/gen_uuid.c
index 5434b523..a90bd8ee 100644
--- a/shlibs/uuid/src/gen_uuid.c
+++ b/shlibs/uuid/src/gen_uuid.c
@@ -248,7 +248,7 @@ static int get_node_id(unsigned char *node_id)
sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
#else
#define ifreq_size(i) sizeof(struct ifreq)
-#endif /* HAVE_SA_LEN*/
+#endif /* HAVE_SA_LEN */
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sd < 0) {
diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am
index 92253334..76828cc1 100644
--- a/sys-utils/Makefile.am
+++ b/sys-utils/Makefile.am
@@ -25,6 +25,7 @@ info_TEXINFOS = ipc.texi
if BUILD_FALLOCATE
usrbin_exec_PROGRAMS += fallocate
+fallocate_SOURCES = fallocate.c ../lib/strtosize.c
dist_man_MANS += fallocate.1
endif
diff --git a/sys-utils/fallocate.1 b/sys-utils/fallocate.1
index 00e973ce..fe0d3108 100644
--- a/sys-utils/fallocate.1
+++ b/sys-utils/fallocate.1
@@ -25,17 +25,18 @@ The exit code returned by
is 0 on success and 1 on failure.
.PP
.SH OPTIONS
+The \fIlength\fR and \fIoffset\fR arguments may be followed by binary (2^N)
+suffixes KiB, MiB, GiB, TiB, PiB and EiB (the "iB" is optional, e.g. "K" has the
+same meaning as "KiB") or decimal (10^N) suffixes KB, MB, GB, PB and EB.
.IP "\fB\-h, \-\-help\fP"
Print help and exit.
.IP "\fB\-n, \-\-keep-size\fP"
Do not modify the apparent length of the file. This may effectively allocate
blocks past EOF, which can be removed with a truncate.
.IP "\fB\-o, \-\-offset\fP \fIoffset\fP
-Specifies the beginning offset of the allocation, in bytes. Suffixes of k, m,
-g, t, p, e may be specified to denote KiB, MiB, GiB, etc.
+Specifies the beginning offset of the allocation, in bytes.
.IP "\fB\-l, \-\-length\fP \fIlength\fP
-Specifies the length of the allocation, in bytes. Suffixes of k, m, g, t, p, e
-may be specified to denote KiB, MiB, GiB, etc.
+Specifies the length of the allocation, in bytes.
.SH AUTHORS
.nf
Eric Sandeen <sandeen@redhat.com>
diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index be715777..e41643a2 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -40,6 +40,7 @@
#include <linux/falloc.h> /* for FALLOC_FL_* flags */
#include "nls.h"
+#include "strtosize.h"
static void __attribute__((__noreturn__)) usage(FILE *out)
@@ -58,47 +59,14 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-#define EXABYTES(x) ((x) << 60)
-#define PETABYTES(x) ((x) << 50)
-#define TERABYTES(x) ((x) << 40)
-#define GIGABYTES(x) ((x) << 30)
-#define MEGABYTES(x) ((x) << 20)
-#define KILOBYTES(x) ((x) << 10)
-
static loff_t cvtnum(char *s)
{
- loff_t i;
- char *sp;
-
- errno = 0;
- i = strtoll(s, &sp, 0);
+ uintmax_t x;
- if ((errno == ERANGE && (i == LLONG_MAX || i == LLONG_MIN)) ||
- (errno != 0 && i == 0))
- return -1LL;
- if (i == 0 && sp == s)
+ if (strtosize(s, &x))
return -1LL;
- if (*sp == '\0')
- return i;
- if (sp[1] != '\0')
- return -1LL;
-
- switch (tolower(*sp)) {
- case 'k':
- return KILOBYTES(i);
- case 'm':
- return MEGABYTES(i);
- case 'g':
- return GIGABYTES(i);
- case 't':
- return TERABYTES(i);
- case 'p':
- return PETABYTES(i);
- case 'e':
- return EXABYTES(i);
- }
- return -1LL;
+ return x;
}
int main(int argc, char **argv)
diff --git a/sys-utils/ldattach.8 b/sys-utils/ldattach.8
index 3856999f..f78ab34c 100644
--- a/sys-utils/ldattach.8
+++ b/sys-utils/ldattach.8
@@ -1,6 +1,6 @@
.\" Copyright 2008 Tilman Schmidt (tilman@imap.cc)
.\" May be distributed under the GNU General Public License version 2 or later
-.TH LDATTACH 8 "14 January 2008" "Linux 2.6" "Linux Programmer's Manual"
+.TH LDATTACH 8 "14 February 2010" "Linux 2.6" "Linux Programmer's Manual"
.SH NAME
ldattach \- attach a line discipline to a serial line
.SH SYNOPSIS
@@ -8,6 +8,8 @@ ldattach \- attach a line discipline to a serial line
.RB [ \-dhV78neo12 ]
.RB [ \-s
.IR speed ]
+.RB [ \-i
+.IR iflag ]
.I ldisc device
.SH DESCRIPTION
The
@@ -122,6 +124,13 @@ Sets the number of stop bits of the serial line to one.
.TP
\fB-2\fP | \fB--twostopbits\fP
Sets the number of stop bits of the serial line to two.
+.TP
+\fB-i\fP \fIvalue\fP | \fB--iflag\fP [\fB-\fP]\fIvalue\fP{,...}
+Sets the specified bits in the c_iflag word of the serial line.
+\fIValue\fP may be a number or a symbolic name.
+If \fIvalue\fP is prefixed by a minus sign, clear the specified bits instead.
+Several comma separated \fIvalue\fPs may be given in order to
+set and clear multiple bits.
.SH "SEE ALSO"
.BR inputattach (1),
.BR ttys (4)
diff --git a/sys-utils/ldattach.c b/sys-utils/ldattach.c
index b4563aee..4fe5a7bb 100644
--- a/sys-utils/ldattach.c
+++ b/sys-utils/ldattach.c
@@ -47,9 +47,14 @@
static const char *progname;
static int debug = 0;
+struct ld_table {
+ const char *name;
+ int value;
+};
+
/* currently supported line disciplines, plus some aliases */
-static const struct ld_entry { const char *s; int v; }
-ld_table[] = {
+static const struct ld_table ld_discs[] =
+{
{ "TTY", N_TTY },
{ "SLIP", N_SLIP },
{ "MOUSE", N_MOUSE },
@@ -68,29 +73,87 @@ ld_table[] = {
{ "GIGASET", N_GIGASET_M101 },
{ "M101", N_GIGASET_M101 },
{ "PPS", N_PPS },
+ { NULL, 0 }
+};
+
+/* known c_iflag names */
+static const struct ld_table ld_iflags[] =
+{
+ { "IGNBRK", IGNBRK },
+ { "BRKINT", BRKINT },
+ { "IGNPAR", IGNPAR },
+ { "PARMRK", PARMRK },
+ { "INPCK", INPCK },
+ { "ISTRIP", ISTRIP },
+ { "INLCR", INLCR },
+ { "IGNCR", IGNCR },
+ { "ICRNL", ICRNL },
+ { "IUCLC", IUCLC },
+ { "IXON", IXON },
+ { "IXANY", IXANY },
+ { "IXOFF", IXOFF },
+ { "IMAXBEL", IMAXBEL },
+ { "IUTF8", IUTF8 },
+ { NULL, 0 }
};
-/* look up line discipline code */
-static int lookup_ld(const char *s)
+static int lookup_table(const struct ld_table *tab, const char *str)
{
- size_t i;
+ const struct ld_table *t;
- for (i = 0; i < ARRAY_SIZE(ld_table); i++)
- if (!strcasecmp(ld_table[i].s, s))
- return ld_table[i].v;
+ for (t = tab; t && t->name; t++)
+ if (!strcasecmp(t->name, str))
+ return t->value;
return -1;
}
+static void print_table(FILE *out, const struct ld_table *tab)
+{
+ const struct ld_table *t;
+ int i;
+
+ for (t = tab, i = 1; t && t->name; t++, i++) {
+ fprintf(out, " %-10s", t->name);
+ if (!(i % 3))
+ fputc('\n', out);
+ }
+}
+
+static int parse_iflag(char *str, int *set_iflag, int *clr_iflag)
+{
+ int iflag;
+ char *s, *end;
+
+ for (s = strtok(str, ","); s != NULL; s = strtok(NULL, ",")) {
+ if (*s == '-')
+ s++;
+ if ((iflag = lookup_table(ld_iflags, s)) < 0) {
+ iflag = strtol(s, &end, 0);
+ if (*end || iflag < 0)
+ errx(EXIT_FAILURE, _("invalid iflag: %s"), s);
+ }
+ if (s > str && *(s - 1) == '-')
+ *clr_iflag |= iflag;
+ else
+ *set_iflag |= iflag;
+ }
+
+ dbg("iflag (set/clear): %d/%d", *set_iflag, *clr_iflag);
+ return 0;
+}
+
+
static void __attribute__((__noreturn__)) usage(int exitcode)
{
- size_t i;
+ FILE *out = exitcode == EXIT_SUCCESS ? stdout : stderr;
- fprintf(stderr,
- _("\nUsage: %s [ -dhV78neo12 ] [ -s <speed> ] <ldisc> <device>\n"),
+ fprintf(out,
+ _("\nUsage: %s [ -dhV78neo12 ] [ -s <speed> ] [ -i [-]<iflag> ] <ldisc> <device>\n"),
progname);
- fputs(_("\nKnown <ldisc> names:\n"), stderr);
- for (i = 0; i < ARRAY_SIZE(ld_table); i++)
- fprintf(stderr, " %s\n", ld_table[i].s);
+ fputs(_("\nKnown <ldisc> names:\n"), out);
+ print_table(out, ld_discs);
+ fputs(_("\nKnown <iflag> names:\n"), out);
+ print_table(out, ld_iflags);
exit(exitcode);
}
@@ -123,6 +186,7 @@ int main(int argc, char **argv)
int tty_fd;
struct termios ts;
int speed = 0, bits = '-', parity = '-', stop = '-';
+ int set_iflag = 0, clr_iflag = 0;
int ldisc;
int optc;
char *end;
@@ -136,13 +200,13 @@ int main(int argc, char **argv)
{"oddparity", 0, 0, 'o'},
{"onestopbit", 0, 0, '1'},
{"twostopbits", 0, 0, '2'},
+ {"iflag", 1, 0, 'i'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'V'},
{"debug", 0, 0, 'd'},
{0, 0, 0, 0}
};
-
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@@ -152,7 +216,7 @@ int main(int argc, char **argv)
if (argc == 0)
usage(EXIT_SUCCESS);
- while ((optc = getopt_long(argc, argv, "dhV78neo12s:", opttbl, NULL)) >= 0) {
+ while ((optc = getopt_long(argc, argv, "dhV78neo12s:i:", opttbl, NULL)) >= 0) {
switch (optc) {
case 'd':
debug++;
@@ -175,6 +239,9 @@ int main(int argc, char **argv)
if (*end || speed <= 0)
errx(EXIT_FAILURE, _("invalid speed: %s"), optarg);
break;
+ case 'i':
+ parse_iflag(optarg, &set_iflag, &clr_iflag);
+ break;
case 'V':
printf(_("ldattach from %s\n"), PACKAGE_STRING);
break;
@@ -190,7 +257,8 @@ int main(int argc, char **argv)
usage(EXIT_FAILURE);
/* parse line discipline specification */
- if ((ldisc = lookup_ld(argv[optind])) < 0) {
+ ldisc = lookup_table(ld_discs, argv[optind]);
+ if (ldisc < 0) {
ldisc = strtol(argv[optind], &end, 0);
if (*end || ldisc < 0)
errx(EXIT_FAILURE, _("invalid line discipline: %s"), argv[optind]);
@@ -240,6 +308,10 @@ int main(int argc, char **argv)
break;
}
ts.c_cflag |= CREAD; /* just to be on the safe side */
+
+ ts.c_iflag |= set_iflag;
+ ts.c_iflag &= ~clr_iflag;
+
if (tcsetattr(tty_fd, TCSAFLUSH, &ts) < 0)
err(EXIT_FAILURE, _("cannot set terminal attributes for %s"), dev);
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index c200fb32..77a3e5c2 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -360,7 +360,7 @@ cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
"=a" (*eax),
"=c" (*ecx),
"=d" (*edx)
- : "0" (op), "c"(0));
+ : "1" (op), "c"(0));
}
static void
diff --git a/sys-utils/rtcwake.8 b/sys-utils/rtcwake.8
index 999b6786..ee7af3a0 100644
--- a/sys-utils/rtcwake.8
+++ b/sys-utils/rtcwake.8
@@ -21,7 +21,7 @@
rtcwake - enter a system sleep state until specified wakeup time
.SH SYNOPSIS
.B rtcwake
-.RB [ \-hvVlua ]
+.RB [ \-hvVluan ]
.RB [ \-d
.IR device ]
.RB [ \-m
@@ -52,11 +52,15 @@ Display a short help message that shows how to use the program.
\fB-V\fP | \fB--version\fP
Displays version information and exists.
.TP
+\fB-n\fP | \fB--dry-run\fP
+This option does everything but actually setup alarm, suspend system or wait
+for the alarm.
+.TP
\fB-a\fP | \fB--auto\fP
Reads the clock mode (whether the hardware clock is set to UTC or local time)
from \fI/etc/adjtime\fP. That's the location where the
.BR hwclock (8)
-stores that information.
+stores that information. This is the default.
.TP
\fB-l\fP | \fB--local\fP
Assumes that the hardware clock is set to local time, regardless of the
@@ -110,6 +114,9 @@ Don't suspend. The rtcwake command sets RTC wakeup time only.
.B on
Don't suspend, but read RTC device until alarm time appears. This mode is
useful for debugging.
+.TP
+.B disable
+Disable previously set alarm.
.RE
.PP
.SH NOTES
diff --git a/sys-utils/rtcwake.c b/sys-utils/rtcwake.c
index 7b2df26a..26511306 100644
--- a/sys-utils/rtcwake.c
+++ b/sys-utils/rtcwake.c
@@ -62,10 +62,12 @@ enum ClockMode {
};
static unsigned verbose;
+static unsigned dryrun;
enum ClockMode clock_mode = CM_AUTO;
static struct option long_options[] = {
{"auto", no_argument, 0, 'a'},
+ {"dry-run", no_argument, 0, 'n'},
{"local", no_argument, 0, 'l'},
{"utc", no_argument, 0, 'u'},
{"verbose", no_argument, 0, 'v'},
@@ -82,6 +84,7 @@ static void usage(int retval)
{
printf(_("usage: %s [options]\n"
" -d | --device <device> select rtc device (rtc0|rtc1|...)\n"
+ " -n | --dry-run does everything, but suspend\n"
" -l | --local RTC uses local timezone\n"
" -m | --mode standby|mem|... sleep mode\n"
" -s | --seconds <seconds> seconds to sleep\n"
@@ -214,8 +217,9 @@ static int setup_alarm(int fd, time_t *wakeup)
wake.time.tm_isdst = -1;
wake.enabled = 1;
+
/* First try the preferred RTC_WKALM_SET */
- if (ioctl(fd, RTC_WKALM_SET, &wake) < 0) {
+ if (!dryrun && ioctl(fd, RTC_WKALM_SET, &wake) < 0) {
wake.enabled = 0;
/* Fall back on the non-preferred way of setting wakeups; only
* works for alarms < 24 hours from now */
@@ -246,8 +250,10 @@ static void suspend_system(const char *suspend)
return;
}
- fprintf(f, "%s\n", suspend);
- fflush(f);
+ if (!dryrun) {
+ fprintf(f, "%s\n", suspend);
+ fflush(f);
+ }
/* this executes after wake from suspend */
fclose(f);
@@ -308,7 +314,7 @@ int main(int argc, char **argv)
progname = basename(argv[0]);
- while ((t = getopt_long(argc, argv, "ahd:lm:s:t:uVv",
+ while ((t = getopt_long(argc, argv, "ahd:lm:ns:t:uVv",
long_options, NULL)) != EOF) {
switch (t) {
case 'a':
@@ -338,6 +344,7 @@ int main(int argc, char **argv)
|| strcmp(optarg, "on") == 0
|| strcmp(optarg, "no") == 0
|| strcmp(optarg, "off") == 0
+ || strcmp(optarg, "disable") == 0
) {
suspend = strdup(optarg);
break;
@@ -347,6 +354,10 @@ int main(int argc, char **argv)
progname, optarg);
usage(EXIT_FAILURE);
+ case 'n':
+ dryrun = 1;
+ break;
+
/* alarm time, seconds-to-sleep (relative) */
case 's':
t = atoi(optarg);
@@ -403,7 +414,7 @@ int main(int argc, char **argv)
printf(clock_mode == CM_UTC ? _("Using UTC time.\n") :
_("Using local time.\n"));
- if (!alarm && !seconds) {
+ if (!alarm && !seconds && strcmp(suspend,"disable")) {
fprintf(stderr, _("%s: must provide wake time\n"), progname);
usage(EXIT_FAILURE);
}
@@ -468,40 +479,62 @@ int main(int argc, char **argv)
fflush(stdout);
usleep(10 * 1000);
- if (strcmp(suspend, "no") == 0)
+ if (strcmp(suspend, "no") == 0) {
+ if (verbose)
+ printf(_("suspend mode: no; leaving\n"));
+ close(fd);
exit(EXIT_SUCCESS);
- else if (strcmp(suspend, "on") != 0) {
- sync();
- suspend_system(suspend);
+
} else if (strcmp(suspend, "off") == 0) {
char *arg[4];
int i = 0;
+ if (verbose)
+ printf(_("suspend mode: off; executing %s\n"),
+ _PATH_SHUTDOWN);
arg[i++] = _PATH_SHUTDOWN;
arg[i++] = "-P";
arg[i++] = "now";
arg[i] = NULL;
- execv(arg[0], arg);
+ if (!dryrun) {
+ execv(arg[0], arg);
- fprintf(stderr, _("%s: unable to execute %s: %s\n"),
+ fprintf(stderr, _("%s: unable to execute %s: %s\n"),
progname, _PATH_SHUTDOWN, strerror(errno));
- rc = EXIT_FAILURE;
- } else {
+ rc = EXIT_FAILURE;
+ }
+
+ } else if (strcmp(suspend, "on") == 0) {
unsigned long data;
- do {
- t = read(fd, &data, sizeof data);
- if (t < 0) {
- perror(_("rtc read"));
- break;
- }
- if (verbose)
- printf("... %s: %03lx\n", devname, data);
- } while (!(data & RTC_AF));
+ if (verbose)
+ printf(_("suspend mode: on; reading rtc\n"));
+
+ if (!dryrun) {
+ do {
+ t = read(fd, &data, sizeof data);
+ if (t < 0) {
+ perror(_("rtc read"));
+ break;
+ }
+ if (verbose)
+ printf("... %s: %03lx\n", devname, data);
+ } while (!(data & RTC_AF));
+ }
+
+ } else if (strcmp(suspend, "disable") == 0) {
+ /* just break, alarm gets disabled in the end */
+ if (verbose)
+ printf(_("suspend mode: disable; disabling alarm\n"));
+ } else {
+ if (verbose)
+ printf(_("suspend mode: %s; suspending system\n"), suspend);
+ sync();
+ suspend_system(suspend);
}
- if (ioctl(fd, RTC_AIE_OFF, 0) < 0)
+ if (!dryrun && ioctl(fd, RTC_AIE_OFF, 0) < 0)
perror(_("disable rtc alarm interrupt"));
close(fd);
diff --git a/sys-utils/unshare.1 b/sys-utils/unshare.1
index 31fcfde7..06e4ac20 100644
--- a/sys-utils/unshare.1
+++ b/sys-utils/unshare.1
@@ -47,6 +47,9 @@ Unshare the IPC namespace,
.TP
.BR \-n , " \-\-net"
Unshare the network namespace.
+.SH NOTES
+The unshare command drops potential privileges before executing the
+target program. This allows to setuid unshare.
.SH SEE ALSO
unshare(2), clone(2)
.SH BUGS
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index df75d177..6b6177c5 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -113,6 +113,13 @@ int main(int argc, char *argv[])
if(-1 == unshare(unshare_flags))
err(EXIT_FAILURE, _("unshare failed"));
+ /* drop potential root euid/egid if we had been setuid'd */
+ if (setgid(getgid()) < 0)
+ err(EXIT_FAILURE, _("cannot set group id"));
+
+ if (setuid(getuid()) < 0)
+ err(EXIT_FAILURE, _("cannot set user id"));
+
execvp(argv[optind], argv + optind);
err(EXIT_FAILURE, _("exec %s failed"), argv[optind]);
diff --git a/tests/README b/tests/README
index 783f37c6..c812a392 100644
--- a/tests/README
+++ b/tests/README
@@ -10,13 +10,18 @@
./run.sh [--verbose]
- Run one tests:
+ Run subset of tests:
- ./ts-<component_name>-<test_name>.sh [--verbose]
+ ./run.sh <test_directory-name>
+
+ for example:
+
+ ./run.sh blkid
+ ./run.sh fdisk
*** WARNING ***
- The tests touch your /etc/fstab and /etc/blkid.tab. Please, be careful and use
+ The tests touch your /etc/fstab. Please, be careful and use
these tests only for development and never on production system.
diff --git a/tests/commands.sh.in b/tests/commands.sh.in
index 8399738c..f52a6868 100644
--- a/tests/commands.sh.in
+++ b/tests/commands.sh.in
@@ -10,6 +10,7 @@ TS_HELPER_BYTESWAP="$TS_TOPDIR/helpers/test_byteswap"
TS_HELPER_MD5="$TS_TOPDIR/helpers/test_md5"
TS_HELPER_ISMOUNTED="$TOPDIR/lib/test_ismounted"
+TS_HELPER_STRTOSIZE="$TOPDIR/lib/test_strtosize"
# TODO: use partx
TS_HELPER_PARTITIONS="$TOPDIR/shlibs/blkid/samples/partitions"
diff --git a/tests/expected/blkid/low-probe-cramfs b/tests/expected/blkid/low-probe-cramfs
index 09ad018c..7898a367 100644
--- a/tests/expected/blkid/low-probe-cramfs
+++ b/tests/expected/blkid/low-probe-cramfs
@@ -1,4 +1,4 @@
-ID_FS_LABEL_ENC=test-cram
ID_FS_LABEL=test-cram
+ID_FS_LABEL_ENC=test-cram
ID_FS_TYPE=cramfs
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-ext2 b/tests/expected/blkid/low-probe-ext2
index fa70cf4f..c70b8569 100644
--- a/tests/expected/blkid/low-probe-ext2
+++ b/tests/expected/blkid/low-probe-ext2
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=test-ext2
ID_FS_LABEL=test-ext2
+ID_FS_LABEL_ENC=test-ext2
ID_FS_TYPE=ext2
ID_FS_USAGE=filesystem
ID_FS_UUID=22f0eac3-5c89-4ec1-9076-60799119aaea
diff --git a/tests/expected/blkid/low-probe-ext3 b/tests/expected/blkid/low-probe-ext3
index 43aeeeda..4bac43f5 100644
--- a/tests/expected/blkid/low-probe-ext3
+++ b/tests/expected/blkid/low-probe-ext3
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=test-ext3
ID_FS_LABEL=test-ext3
+ID_FS_LABEL_ENC=test-ext3
ID_FS_SEC_TYPE=ext2
ID_FS_TYPE=ext3
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-fat b/tests/expected/blkid/low-probe-fat
index 3aecdb45..42012111 100644
--- a/tests/expected/blkid/low-probe-fat
+++ b/tests/expected/blkid/low-probe-fat
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=TEST-FAT
ID_FS_LABEL=TEST-FAT
+ID_FS_LABEL_ENC=TEST-FAT
ID_FS_SEC_TYPE=msdos
ID_FS_TYPE=vfat
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-gfs2 b/tests/expected/blkid/low-probe-gfs2
index a19789ef..cd5a664b 100644
--- a/tests/expected/blkid/low-probe-gfs2
+++ b/tests/expected/blkid/low-probe-gfs2
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=mycluster:mygfs2
ID_FS_LABEL=mycluster:mygfs2
+ID_FS_LABEL_ENC=mycluster:mygfs2
ID_FS_TYPE=gfs2
ID_FS_USAGE=filesystem
ID_FS_VERSION=1
diff --git a/tests/expected/blkid/low-probe-hpfs b/tests/expected/blkid/low-probe-hpfs
index f0711555..47ae1af2 100644
--- a/tests/expected/blkid/low-probe-hpfs
+++ b/tests/expected/blkid/low-probe-hpfs
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=P01\x20S16A
ID_FS_LABEL=P01_S16A
+ID_FS_LABEL_ENC=P01\x20S16A
ID_FS_TYPE=hpfs
ID_FS_USAGE=filesystem
ID_FS_UUID=3BC2-32D5
diff --git a/tests/expected/blkid/low-probe-iso b/tests/expected/blkid/low-probe-iso
index 31a51160..595a1acf 100644
--- a/tests/expected/blkid/low-probe-iso
+++ b/tests/expected/blkid/low-probe-iso
@@ -1,4 +1,4 @@
-ID_FS_LABEL_ENC=IsoVolumeName
ID_FS_LABEL=IsoVolumeName
+ID_FS_LABEL_ENC=IsoVolumeName
ID_FS_TYPE=iso9660
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-iso-joliet b/tests/expected/blkid/low-probe-iso-joliet
index 4d21557c..2810f792 100644
--- a/tests/expected/blkid/low-probe-iso-joliet
+++ b/tests/expected/blkid/low-probe-iso-joliet
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=ThisWonderfulLabelIsVeryVeryLong
ID_FS_LABEL=ThisWonderfulLabelIsVeryVeryLong
+ID_FS_LABEL_ENC=ThisWonderfulLabelIsVeryVeryLong
ID_FS_TYPE=iso9660
ID_FS_USAGE=filesystem
ID_FS_VERSION=Joliet\x20Extension
diff --git a/tests/expected/blkid/low-probe-iso-rr-joliet b/tests/expected/blkid/low-probe-iso-rr-joliet
index 0b3acffa..f0b82c96 100644
--- a/tests/expected/blkid/low-probe-iso-rr-joliet
+++ b/tests/expected/blkid/low-probe-iso-rr-joliet
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=ThisIsVolumeName
ID_FS_LABEL=ThisIsVolumeName
+ID_FS_LABEL_ENC=ThisIsVolumeName
ID_FS_TYPE=iso9660
ID_FS_USAGE=filesystem
ID_FS_VERSION=Joliet\x20Extension
diff --git a/tests/expected/blkid/low-probe-jfs b/tests/expected/blkid/low-probe-jfs
index 08f9c1e6..877fd168 100644
--- a/tests/expected/blkid/low-probe-jfs
+++ b/tests/expected/blkid/low-probe-jfs
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=test-jfs
ID_FS_LABEL=test-jfs
+ID_FS_LABEL_ENC=test-jfs
ID_FS_TYPE=jfs
ID_FS_USAGE=filesystem
ID_FS_UUID=9bf7b82e-7583-4c74-99a4-189a691f27b5
diff --git a/tests/expected/blkid/low-probe-lvm2 b/tests/expected/blkid/low-probe-lvm2
index 5c8e48f9..19aed2aa 100644
--- a/tests/expected/blkid/low-probe-lvm2
+++ b/tests/expected/blkid/low-probe-lvm2
@@ -1,5 +1,5 @@
ID_FS_TYPE=LVM2_member
ID_FS_USAGE=raid
-ID_FS_UUID_ENC=Vynv4k-APH8-xQER-HSBb-8VJ3-SvFF-PB5O1U
ID_FS_UUID=Vynv4k-APH8-xQER-HSBb-8VJ3-SvFF-PB5O1U
+ID_FS_UUID_ENC=Vynv4k-APH8-xQER-HSBb-8VJ3-SvFF-PB5O1U
ID_FS_VERSION=LVM2\x20001
diff --git a/tests/expected/blkid/low-probe-ntfs b/tests/expected/blkid/low-probe-ntfs
index 019e4cec..aaaa077d 100644
--- a/tests/expected/blkid/low-probe-ntfs
+++ b/tests/expected/blkid/low-probe-ntfs
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=Новый\x20том
ID_FS_LABEL=Новый_том
+ID_FS_LABEL_ENC=Новый\x20том
ID_FS_TYPE=ntfs
ID_FS_USAGE=filesystem
ID_FS_UUID=09CBB6DE30C87310
diff --git a/tests/expected/blkid/low-probe-ocfs2 b/tests/expected/blkid/low-probe-ocfs2
index 2463e2ad..2328d21a 100644
--- a/tests/expected/blkid/low-probe-ocfs2
+++ b/tests/expected/blkid/low-probe-ocfs2
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=test-ocfs2
ID_FS_LABEL=test-ocfs2
+ID_FS_LABEL_ENC=test-ocfs2
ID_FS_TYPE=ocfs2
ID_FS_USAGE=filesystem
ID_FS_UUID=6b6bfbea-3a79-4f0c-b166-a20776102445
diff --git a/tests/expected/blkid/low-probe-reiser3 b/tests/expected/blkid/low-probe-reiser3
index 7d9e0147..d376ecae 100644
--- a/tests/expected/blkid/low-probe-reiser3
+++ b/tests/expected/blkid/low-probe-reiser3
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=TESTREISER
ID_FS_LABEL=TESTREISER
+ID_FS_LABEL_ENC=TESTREISER
ID_FS_TYPE=reiserfs
ID_FS_USAGE=filesystem
ID_FS_UUID=9efe7863-b124-46dc-ad68-8ecd04230a7b
diff --git a/tests/expected/blkid/low-probe-reiser4 b/tests/expected/blkid/low-probe-reiser4
index f1d98b94..65d63aa6 100644
--- a/tests/expected/blkid/low-probe-reiser4
+++ b/tests/expected/blkid/low-probe-reiser4
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=TESTR4
ID_FS_LABEL=TESTR4
+ID_FS_LABEL_ENC=TESTR4
ID_FS_TYPE=reiser4
ID_FS_USAGE=filesystem
ID_FS_UUID=9722633c-d69a-4881-b1c8-bedecbbf39d2
diff --git a/tests/expected/blkid/low-probe-romfs b/tests/expected/blkid/low-probe-romfs
index a33b6f3d..2eb982bc 100644
--- a/tests/expected/blkid/low-probe-romfs
+++ b/tests/expected/blkid/low-probe-romfs
@@ -1,4 +1,4 @@
-ID_FS_LABEL_ENC=test-romfs
ID_FS_LABEL=test-romfs
+ID_FS_LABEL_ENC=test-romfs
ID_FS_TYPE=romfs
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-small-fat32 b/tests/expected/blkid/low-probe-small-fat32
index 2315c4d5..39239e6b 100644
--- a/tests/expected/blkid/low-probe-small-fat32
+++ b/tests/expected/blkid/low-probe-small-fat32
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=TESTVFAT
ID_FS_LABEL=TESTVFAT
+ID_FS_LABEL_ENC=TESTVFAT
ID_FS_TYPE=vfat
ID_FS_USAGE=filesystem
ID_FS_UUID=1423-AAE1
diff --git a/tests/expected/blkid/low-probe-swap1 b/tests/expected/blkid/low-probe-swap1
index 537f754d..e078d999 100644
--- a/tests/expected/blkid/low-probe-swap1
+++ b/tests/expected/blkid/low-probe-swap1
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=SWAP-TEST
ID_FS_LABEL=SWAP-TEST
+ID_FS_LABEL_ENC=SWAP-TEST
ID_FS_TYPE=swap
ID_FS_USAGE=other
ID_FS_UUID=8ff8e77f-8553-485e-8656-58be67a81666
diff --git a/tests/expected/blkid/low-probe-tuxonice b/tests/expected/blkid/low-probe-tuxonice
new file mode 100644
index 00000000..3fd5a94d
--- /dev/null
+++ b/tests/expected/blkid/low-probe-tuxonice
@@ -0,0 +1,5 @@
+ID_FS_TYPE=swsuspend
+ID_FS_USAGE=other
+ID_FS_UUID=7ec1e8e4-0a69-4565-860c-3f13b0f79838
+ID_FS_UUID_ENC=7ec1e8e4-0a69-4565-860c-3f13b0f79838
+ID_FS_VERSION=tuxonice
diff --git a/tests/expected/blkid/low-probe-udf b/tests/expected/blkid/low-probe-udf
index 392eac4f..ec249639 100644
--- a/tests/expected/blkid/low-probe-udf
+++ b/tests/expected/blkid/low-probe-udf
@@ -1,4 +1,4 @@
-ID_FS_LABEL_ENC=test-udf
ID_FS_LABEL=test-udf
+ID_FS_LABEL_ENC=test-udf
ID_FS_TYPE=udf
ID_FS_USAGE=filesystem
diff --git a/tests/expected/blkid/low-probe-vmfs b/tests/expected/blkid/low-probe-vmfs
index 1618e30c..41914b0f 100644
--- a/tests/expected/blkid/low-probe-vmfs
+++ b/tests/expected/blkid/low-probe-vmfs
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=toto
ID_FS_LABEL=toto
+ID_FS_LABEL_ENC=toto
ID_FS_TYPE=VMFS
ID_FS_USAGE=filesystem
ID_FS_UUID=49edf844-ebfc28f3-65cb-0021280083cf
diff --git a/tests/expected/blkid/low-probe-xfs b/tests/expected/blkid/low-probe-xfs
index 9dbaf445..f21d881a 100644
--- a/tests/expected/blkid/low-probe-xfs
+++ b/tests/expected/blkid/low-probe-xfs
@@ -1,5 +1,5 @@
-ID_FS_LABEL_ENC=test-xfs
ID_FS_LABEL=test-xfs
+ID_FS_LABEL_ENC=test-xfs
ID_FS_TYPE=xfs
ID_FS_USAGE=filesystem
ID_FS_UUID=8c8a0a5a-9f57-492e-9610-45a61f38f58a
diff --git a/tests/expected/blkid/low-probe-zfs b/tests/expected/blkid/low-probe-zfs
index 94cec8b3..46727de8 100644
--- a/tests/expected/blkid/low-probe-zfs
+++ b/tests/expected/blkid/low-probe-zfs
@@ -1,3 +1,9 @@
-ID_FS_TYPE=zfs
-ID_FS_USAGE=filesystem
-ID_FS_VERSION=1
+ID_FS_LABEL=tank
+ID_FS_LABEL_ENC=tank
+ID_FS_TYPE=zfs_member
+ID_FS_USAGE=raid
+ID_FS_UUID=1782036546311300980
+ID_FS_UUID_ENC=1782036546311300980
+ID_FS_UUID_SUB=13179280127379850514
+ID_FS_UUID_SUB_ENC=13179280127379850514
+ID_FS_VERSION=8
diff --git a/tests/expected/blkid/md-raid1-part b/tests/expected/blkid/md-raid1-part
new file mode 100644
index 00000000..d770a741
--- /dev/null
+++ b/tests/expected/blkid/md-raid1-part
@@ -0,0 +1,66 @@
+Create partitions
+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)
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 1): First sector (2048-104447, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-104447, default 104447):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 2): First sector (53248-104447, default 53248): Using default value 53248
+Last sector, +sectors or +size{K,M,G} (53248-104447, default 104447): Using default value 104447
+
+Command (m for help):
+Disk /dev/sdb: 53 MB, 53477376 bytes
+32 heads, 32 sectors/track, 102 cylinders, total 104448 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 32768 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 2048 53247 25600 83 Linux
+/dev/sdb2 53248 104447 25600 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Create RAID1 device
+Probe whole-disk
+ID_PART_TABLE_TYPE=dos
+Probe first RAID member
+ID_FS_TYPE=linux_raid_member
+ID_FS_USAGE=raid
+
+
+ID_FS_VERSION=0.90.0
+ID_PART_ENTRY_NUMBER=1
+ID_PART_ENTRY_SCHEME=dos
+ID_PART_ENTRY_TYPE=0x83
+ID_PART_ENTRY_TYPE_ENC=0x83
+Probe second RAID member
+ID_FS_TYPE=linux_raid_member
+ID_FS_USAGE=raid
+
+
+ID_FS_VERSION=0.90.0
+ID_PART_ENTRY_NUMBER=2
+ID_PART_ENTRY_SCHEME=dos
+ID_PART_ENTRY_TYPE=0x83
+ID_PART_ENTRY_TYPE_ENC=0x83
diff --git a/tests/expected/blkid/md-raid1-whole b/tests/expected/blkid/md-raid1-whole
new file mode 100644
index 00000000..670a6023
--- /dev/null
+++ b/tests/expected/blkid/md-raid1-whole
@@ -0,0 +1,58 @@
+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)
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 1): First sector (2048-102271, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-102271, default 102271):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4, default 2): First sector (22528-102271, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-102271, default 102271):
+Command (m for help):
+Disk /dev/md8: 52 MB, 52363264 bytes
+2 heads, 4 sectors/track, 12784 cylinders, total 102272 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/md8p1 2048 22527 10240 83 Linux
+/dev/md8p2 22528 43007 10240 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/align-512-4K b/tests/expected/fdisk/align-512-4K
new file mode 100644
index 00000000..9613e176
--- /dev/null
+++ b/tests/expected/fdisk/align-512-4K
@@ -0,0 +1,78 @@
+Create partitions
+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)
+
+The device presents a logical sector size that is smaller than
+the physical sector size. Aligning to a physical sector (or optimal
+I/O) size boundary is recommended, or performance may be impacted.
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (2048-102399, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (22528-102399, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (43008-102399, default 43008): Using default value 43008
+Last sector, +sectors or +size{K,M,G} (43008-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Selected partition 4
+First sector (63488-102399, default 63488): Using default value 63488
+Last sector, +sectors or +size{K,M,G} (63488-102399, default 102399): Using default value 102399
+
+Command (m for help): First sector (65536-102399, default 65536): Using default value 65536
+Last sector, +sectors or +size{K,M,G} (65536-102399, default 102399):
+Command (m for help): First sector (77824-102399, default 77824): Using default value 77824
+Last sector, +sectors or +size{K,M,G} (77824-102399, default 102399):
+Command (m for help): First sector (90112-102399, default 90112): Using default value 90112
+Last sector, +sectors or +size{K,M,G} (90112-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/sdb: 52 MB, 52428800 bytes
+32 heads, 32 sectors/track, 100 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 4096 bytes
+I/O size (minimum/optimal): 4096 bytes / 32768 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 2048 22527 10240 83 Linux
+/dev/sdb2 22528 43007 10240 83 Linux
+/dev/sdb3 43008 63487 10240 83 Linux
+/dev/sdb4 63488 102399 19456 5 Extended
+/dev/sdb5 65536 75775 5120 83 Linux
+/dev/sdb6 77824 88063 5120 83 Linux
+/dev/sdb7 90112 102399 6144 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets:
+0
+0
+0
+0
+0
+0
+0
diff --git a/tests/expected/fdisk/align-512-4K-63 b/tests/expected/fdisk/align-512-4K-63
new file mode 100644
index 00000000..95e3bd9b
--- /dev/null
+++ b/tests/expected/fdisk/align-512-4K-63
@@ -0,0 +1,79 @@
+Create partitions
+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)
+
+The device presents a logical sector size that is smaller than
+the physical sector size. Aligning to a physical sector (or optimal
+I/O) size boundary is recommended, or performance may be impacted.
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (7-102399, default 7): Using default value 7
+Last sector, +sectors or +size{K,M,G} (7-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (20487-102399, default 20487): Using default value 20487
+Last sector, +sectors or +size{K,M,G} (20487-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (40967-102399, default 40967): Using default value 40967
+Last sector, +sectors or +size{K,M,G} (40967-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Selected partition 4
+First sector (61447-102399, default 61447): Using default value 61447
+Last sector, +sectors or +size{K,M,G} (61447-102399, default 102399): Using default value 102399
+
+Command (m for help): First sector (61454-102399, default 63487): Using default value 63487
+Last sector, +sectors or +size{K,M,G} (63487-102399, default 102399):
+Command (m for help): First sector (61454-102399, default 75775): Using default value 75775
+Last sector, +sectors or +size{K,M,G} (75775-102399, default 102399):
+Command (m for help): First sector (61454-102399, default 88063): Using default value 88063
+Last sector, +sectors or +size{K,M,G} (88063-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/sdb: 52 MB, 52428800 bytes
+32 heads, 32 sectors/track, 100 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 4096 bytes
+I/O size (minimum/optimal): 4096 bytes / 32768 bytes
+Alignment offset: 3584 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 7 20486 10240 83 Linux
+/dev/sdb2 20487 40966 10240 83 Linux
+/dev/sdb3 40967 61446 10240 83 Linux
+/dev/sdb4 61447 102399 20476+ 5 Extended
+/dev/sdb5 63487 73726 5120 83 Linux
+/dev/sdb6 75775 86014 5120 83 Linux
+/dev/sdb7 88063 102399 7168+ 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets:
+0
+0
+0
+0
+0
+0
+0
diff --git a/tests/expected/fdisk/align-512-4K-md b/tests/expected/fdisk/align-512-4K-md
new file mode 100644
index 00000000..026b94a6
--- /dev/null
+++ b/tests/expected/fdisk/align-512-4K-md
@@ -0,0 +1,99 @@
+Create partitions
+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)
+
+The device presents a logical sector size that is smaller than
+the physical sector size. Aligning to a physical sector (or optimal
+I/O) size boundary is recommended, or performance may be impacted.
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (2048-102399, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (43008-102399, default 43008): Using default value 43008
+Last sector, +sectors or +size{K,M,G} (43008-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/sdb: 52 MB, 52428800 bytes
+32 heads, 32 sectors/track, 100 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 4096 bytes
+I/O size (minimum/optimal): 4096 bytes / 32768 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 2048 43007 20480 83 Linux
+/dev/sdb2 43008 102399 29696 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets:
+0
+0
+Create partitions (MD)
+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)
+
+The device presents a logical sector size that is smaller than
+the physical sector size. Aligning to a physical sector (or optimal
+I/O) size boundary is recommended, or performance may be impacted.
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (2048-100095, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-100095, default 100095):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (22528-100095, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-100095, default 100095):
+Command (m for help):
+Disk /dev/md8: 51 MB, 51249152 bytes
+2 heads, 4 sectors/track, 12512 cylinders, total 100096 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 4096 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 43007 10240 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets (MD):
+0
+0
diff --git a/tests/expected/fdisk/align-512-4K-topology b/tests/expected/fdisk/align-512-4K-topology
new file mode 100644
index 00000000..88f5f370
--- /dev/null
+++ b/tests/expected/fdisk/align-512-4K-topology
@@ -0,0 +1,78 @@
+Create partitions
+Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
+Building a new DOS disklabel with disk identifier 0x817cb84a.
+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)
+
+The device presents a logical sector size that is smaller than
+the physical sector size. Aligning to a physical sector (or optimal
+I/O) size boundary is recommended, or performance may be impacted.
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (64-102399, default 64): Using default value 64
+Last sector, +sectors or +size{K,M,G} (64-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (20544-102399, default 20544): Using default value 20544
+Last sector, +sectors or +size{K,M,G} (20544-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (41024-102399, default 41024): Using default value 41024
+Last sector, +sectors or +size{K,M,G} (41024-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Selected partition 4
+First sector (61504-102399, default 61504): Using default value 61504
+Last sector, +sectors or +size{K,M,G} (61504-102399, default 102399): Using default value 102399
+
+Command (m for help): First sector (61568-102399, default 61568): Using default value 61568
+Last sector, +sectors or +size{K,M,G} (61568-102399, default 102399):
+Command (m for help): First sector (71872-102399, default 71872): Using default value 71872
+Last sector, +sectors or +size{K,M,G} (71872-102399, default 102399):
+Command (m for help): First sector (82176-102399, default 82176): Using default value 82176
+Last sector, +sectors or +size{K,M,G} (82176-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/sdb: 52 MB, 52428800 bytes
+32 heads, 32 sectors/track, 100 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 4096 bytes
+I/O size (minimum/optimal): 4096 bytes / 32768 bytes
+Disk identifier: 0x817cb84a
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 64 20543 10240 83 Linux
+/dev/sdb2 20544 41023 10240 83 Linux
+/dev/sdb3 41024 61503 10240 83 Linux
+/dev/sdb4 61504 102399 20448 5 Extended
+/dev/sdb5 61568 71807 5120 83 Linux
+/dev/sdb6 71872 82111 5120 83 Linux
+/dev/sdb7 82176 102399 10112 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets:
+0
+0
+0
+0
+0
+0
+0
diff --git a/tests/expected/fdisk/align-512-512 b/tests/expected/fdisk/align-512-512
new file mode 100644
index 00000000..e984d6bc
--- /dev/null
+++ b/tests/expected/fdisk/align-512-512
@@ -0,0 +1,63 @@
+Create partitions
+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)
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (2048-102399, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (22528-102399, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (43008-102399, default 43008): Using default value 43008
+Last sector, +sectors or +size{K,M,G} (43008-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Selected partition 4
+First sector (63488-102399, default 63488): Using default value 63488
+Last sector, +sectors or +size{K,M,G} (63488-102399, default 102399): Using default value 102399
+
+Command (m for help): First sector (65536-102399, default 65536): Using default value 65536
+Last sector, +sectors or +size{K,M,G} (65536-102399, default 102399):
+Command (m for help): First sector (77824-102399, default 77824): Using default value 77824
+Last sector, +sectors or +size{K,M,G} (77824-102399, default 102399):
+Command (m for help): First sector (90112-102399, default 90112): Using default value 90112
+Last sector, +sectors or +size{K,M,G} (90112-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/loop0: 52 MB, 52428800 bytes
+255 heads, 63 sectors/track, 6 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/loop0p1 2048 22527 10240 83 Linux
+/dev/loop0p2 22528 43007 10240 83 Linux
+/dev/loop0p3 43008 63487 10240 83 Linux
+/dev/loop0p4 63488 102399 19456 5 Extended
+/dev/loop0p5 65536 75775 5120 83 Linux
+/dev/loop0p6 77824 88063 5120 83 Linux
+/dev/loop0p7 90112 102399 6144 83 Linux
+
+Command (m for help):
diff --git a/tests/expected/fdisk/align-512-512-topology b/tests/expected/fdisk/align-512-512-topology
new file mode 100644
index 00000000..91cd1b4f
--- /dev/null
+++ b/tests/expected/fdisk/align-512-512-topology
@@ -0,0 +1,74 @@
+Create partitions
+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)
+
+WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
+ switch off the mode (command 'c') and change display units to
+ sectors (command 'u').
+
+Command (m for help): DOS Compatibility flag is not set
+
+Command (m for help): Changing display/entry units to sectors
+
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (2048-102399, default 2048): Using default value 2048
+Last sector, +sectors or +size{K,M,G} (2048-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (22528-102399, default 22528): Using default value 22528
+Last sector, +sectors or +size{K,M,G} (22528-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Partition number (1-4): First sector (43008-102399, default 43008): Using default value 43008
+Last sector, +sectors or +size{K,M,G} (43008-102399, default 102399):
+Command (m for help): Command action
+ e extended
+ p primary partition (1-4)
+Selected partition 4
+First sector (63488-102399, default 63488): Using default value 63488
+Last sector, +sectors or +size{K,M,G} (63488-102399, default 102399): Using default value 102399
+
+Command (m for help): First sector (65536-102399, default 65536): Using default value 65536
+Last sector, +sectors or +size{K,M,G} (65536-102399, default 102399):
+Command (m for help): First sector (77824-102399, default 77824): Using default value 77824
+Last sector, +sectors or +size{K,M,G} (77824-102399, default 102399):
+Command (m for help): First sector (90112-102399, default 90112): Using default value 90112
+Last sector, +sectors or +size{K,M,G} (90112-102399, default 102399): Using default value 102399
+
+Command (m for help):
+Disk /dev/sdb: 52 MB, 52428800 bytes
+32 heads, 32 sectors/track, 100 cylinders, total 102400 sectors
+Units = sectors of 1 * 512 = 512 bytes
+Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 32768 bytes
+
+
+ Device Boot Start End Blocks Id System
+/dev/sdb1 2048 22527 10240 83 Linux
+/dev/sdb2 22528 43007 10240 83 Linux
+/dev/sdb3 43008 63487 10240 83 Linux
+/dev/sdb4 63488 102399 19456 5 Extended
+/dev/sdb5 65536 75775 5120 83 Linux
+/dev/sdb6 77824 88063 5120 83 Linux
+/dev/sdb7 90112 102399 6144 83 Linux
+
+Command (m for help): The partition table has been altered!
+
+Calling ioctl() to re-read partition table.
+Syncing disks.
+Alignment offsets:
+0
+0
+0
+0
+0
+0
+0
diff --git a/tests/expected/fdisk/oddinput b/tests/expected/fdisk/oddinput
index f1bfda55..7fd14b51 100644
--- a/tests/expected/fdisk/oddinput
+++ b/tests/expected/fdisk/oddinput
@@ -3,10 +3,11 @@ f1c9645dbc14efddc7d8a322685f26eb oddinput.img
Empty image listing
Disk testimage doesn't contain a valid partition table
-Disk testimage: 0 MB, 0 bytes
-255 heads, 63 sectors/track, 0 cylinders
+Disk testimage: 10 MB, 10485760 bytes
+255 heads, 63 sectors/track, 1 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
+I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Nonexistant file
diff --git a/tests/expected/misc/strtosize b/tests/expected/misc/strtosize
new file mode 100644
index 00000000..04a2d590
--- /dev/null
+++ b/tests/expected/misc/strtosize
@@ -0,0 +1,30 @@
+test_strtosize: invalid size '-1' value
+ 0 : 0
+ 1 : 1
+ 123 : 123
+ 18446744073709551615 : 18446744073709551615
+ 1K : 1024
+ 1KiB : 1024
+ 1M : 1048576
+ 1MiB : 1048576
+ 1G : 1073741824
+ 1GiB : 1073741824
+ 1T : 1099511627776
+ 1TiB : 1099511627776
+ 1P : 1125899906842624
+ 1PiB : 1125899906842624
+ 1E : 1152921504606846976
+ 1EiB : 1152921504606846976
+ 1KB : 1000
+ 1MB : 1000000
+ 1GB : 1000000000
+ 1TB : 1000000000000
+ 1PB : 1000000000000000
+ 1EB : 1000000000000000000
+test_strtosize: invalid size '' value
+test_strtosize: invalid size ' ' value
+ 1 : 1
+test_strtosize: invalid size '1 ' value
+ 0x0a : 10
+ 0xff00 : 65280
+ 0x80000000 : 2147483648
diff --git a/tests/functions.sh b/tests/functions.sh
index eb9a878d..d79c9808 100644
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -78,7 +78,12 @@ function ts_has_option {
function ts_init_env {
local mydir=$(ts_abspath $(dirname $0))
- export LANG="en_US.UTF-8"
+ LANG="POSIX"
+ LANGUAGE="POSIX"
+ LC_ALL="POSIX"
+ CHARSET="UTF-8"
+
+ export LANG LANGUAGE LC_ALL CHARSET
TS_TOPDIR=$(ts_abspath $mydir/../../)
TS_SCRIPT="$mydir/$(basename $0)"
@@ -255,8 +260,8 @@ function ts_image_init {
}
function ts_device_init {
- local img=$(ts_image_init)
- local dev=$($TS_CMD_LOSETUP -s -f "$img")
+ local img=$(ts_image_init $1 $2)
+ local dev=$($TS_CMD_LOSETUP --show -f "$img")
if [ -z "$dev" ]; then
ts_device_deinit $dev
diff --git a/tests/ts/blkid/images-fs/tuxonice.img.bz2 b/tests/ts/blkid/images-fs/tuxonice.img.bz2
new file mode 100644
index 00000000..c47ab3e8
--- /dev/null
+++ b/tests/ts/blkid/images-fs/tuxonice.img.bz2
Binary files differ
diff --git a/tests/ts/blkid/md-raid1-part b/tests/ts/blkid/md-raid1-part
new file mode 100755
index 00000000..1d55f6bb
--- /dev/null
+++ b/tests/ts/blkid/md-raid1-part
@@ -0,0 +1,92 @@
+#!/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 raid1 (last partition)"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+modprobe --dry-run --quiet scsi_debug
+[ "$?" == 0 ] || ts_skip "missing scsi_debug module"
+[ -x /sbin/mdadm ] || ts_skip "missing mdadm"
+
+rmmod scsi_debug &> /dev/null
+modprobe scsi_debug dev_size_mb=51 sector_size=512
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+sleep 3
+
+DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}')
+[ "x${DEVNAME}" == "x" ] && ts_die "Cannot found device"
+
+DEVICE="/dev/${DEVNAME}"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++25M
+n
+p
+2
+
+
+p
+w
+q
+EOF
+
+sleep 3
+MD_DEVNAME=md8
+MD_DEVICE=/dev/${MD_DEVNAME}
+
+###exit 1
+
+ts_log "Create RAID1 device"
+/sbin/mdadm -q -S ${MD_DEVICE} &> /dev/null
+/sbin/mdadm -q --create ${MD_DEVICE} --metadata=0.90 --chunk=64 --level=1 \
+ --raid-devices=2 ${DEVICE}1 ${DEVICE}2 >> $TS_OUTPUT 2>&1
+
+sleep 3
+
+ts_log "Probe whole-disk"
+$TS_CMD_BLKID -p -o udev ${DEVICE} 2>&1 | sort >> $TS_OUTPUT
+
+ts_log "Probe first RAID member"
+$TS_CMD_BLKID -p -o udev ${DEVICE}1 2>&1 | sort >> $TS_OUTPUT
+
+ts_log "Probe second RAID member"
+$TS_CMD_BLKID -p -o udev ${DEVICE}2 2>&1 | sort >> $TS_OUTPUT
+
+/sbin/mdadm -q -S ${MD_DEVICE} >> $TS_OUTPUT 2>&1
+
+sleep 3
+rmmod scsi_debug
+
+# 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/blkid/md-raid1-whole b/tests/ts/blkid/md-raid1-whole
new file mode 100755
index 00000000..4589dcff
--- /dev/null
+++ b/tests/ts/blkid/md-raid1-whole
@@ -0,0 +1,88 @@
+#!/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 raid1 (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=1 \
+ --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
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+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/align-512-4K b/tests/ts/fdisk/align-512-4K
new file mode 100755
index 00000000..329d4308
--- /dev/null
+++ b/tests/ts/fdisk/align-512-4K
@@ -0,0 +1,91 @@
+#!/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.
+#
+
+
+#
+# Test alignment for 512/512 disk *with* topology -- aligned to optimal
+# I/O size (32KiB)
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="align 512/4K"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+modprobe --dry-run --quiet scsi_debug
+[ "$?" == 0 ] || ts_skip "missing scsi_debug module"
+
+rmmod scsi_debug &> /dev/null
+modprobe scsi_debug dev_size_mb=50 sector_size=512 physblk_exp=3
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+sleep 3
+
+DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}')
+[ "x${DEVNAME}" == "x" ] && ts_die "Cannot found device"
+
+DEVICE="/dev/${DEVNAME}"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+n
+p
+3
+
++10M
+n
+e
+
+
+n
+
++5M
+n
+
++5M
+n
+
+
+p
+w
+q
+EOF
+
+ts_log "Alignment offsets:"
+cat /sys/block/${DEVNAME}/${DEVNAME}{1,2,3,4,5,6,7}/alignment_offset >> $TS_OUTPUT 2>&1
+
+sleep 3
+rmmod scsi_debug
+
+# remove disk ID
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/align-512-4K-63 b/tests/ts/fdisk/align-512-4K-63
new file mode 100755
index 00000000..1963dd09
--- /dev/null
+++ b/tests/ts/fdisk/align-512-4K-63
@@ -0,0 +1,91 @@
+#!/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.
+#
+
+
+#
+# Test alignment for 512/512 disk *with* topology -- aligned to optimal
+# I/O size (32KiB)
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="align 512/4K +alignment_offset"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+modprobe --dry-run --quiet scsi_debug
+[ "$?" == 0 ] || ts_skip "missing scsi_debug module"
+
+rmmod scsi_debug &> /dev/null
+modprobe scsi_debug dev_size_mb=50 sector_size=512 physblk_exp=3 lowest_aligned=7
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+sleep 3
+
+DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}')
+[ "x${DEVNAME}" == "x" ] && ts_die "Cannot found device"
+
+DEVICE="/dev/${DEVNAME}"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+n
+p
+3
+
++10M
+n
+e
+
+
+n
+
++5M
+n
+
++5M
+n
+
+
+p
+w
+q
+EOF
+
+ts_log "Alignment offsets:"
+cat /sys/block/${DEVNAME}/${DEVNAME}{1,2,3,4,5,6,7}/alignment_offset >> $TS_OUTPUT 2>&1
+
+sleep 3
+rmmod scsi_debug
+
+# remove disk ID
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/align-512-4K-md b/tests/ts/fdisk/align-512-4K-md
new file mode 100755
index 00000000..ed0ec156
--- /dev/null
+++ b/tests/ts/fdisk/align-512-4K-md
@@ -0,0 +1,105 @@
+#!/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.
+#
+
+
+#
+# Test alignment for 512/512 disk *with* topology -- aligned to optimal
+# I/O size (32KiB)
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="align 512/4K +MD"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+modprobe --dry-run --quiet scsi_debug
+[ "$?" == 0 ] || ts_skip "missing scsi_debug module"
+[ -x /sbin/mdadm ] || ts_skip "missing mdadm"
+
+rmmod scsi_debug &> /dev/null
+modprobe scsi_debug dev_size_mb=50 sector_size=512 physblk_exp=3
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+sleep 3
+
+DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}')
+[ "x${DEVNAME}" == "x" ] && ts_die "Cannot found device"
+
+DEVICE="/dev/${DEVNAME}"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++20M
+n
+p
+2
+
+
+p
+w
+q
+EOF
+
+ts_log "Alignment offsets:"
+cat /sys/block/${DEVNAME}/${DEVNAME}{1,2}/alignment_offset >> $TS_OUTPUT 2>&1
+
+sleep 3
+MD_DEVNAME=md8
+MD_DEVICE=/dev/${MD_DEVNAME}
+
+/sbin/mdadm -q -S ${MD_DEVICE} &> /dev/null
+/sbin/mdadm -q --create ${MD_DEVICE} --metadata=0.90 --chunk=64 \
+ --level=0 --raid-devices=2 ${DEVICE}1 ${DEVICE}2 >> $TS_OUTPUT 2>&1
+
+ts_log "Create partitions (MD)"
+$TS_CMD_FDISK ${MD_DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+p
+w
+q
+EOF
+
+ts_log "Alignment offsets (MD):"
+cat /sys/block/${MD_DEVNAME}/${MD_DEVNAME}p{1,2}/alignment_offset >> $TS_OUTPUT 2>&1
+
+sleep 3
+/sbin/mdadm -q -S ${MD_DEVICE} >> $TS_OUTPUT 2>&1
+rmmod scsi_debug
+
+# remove disk ID
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/align-512-512 b/tests/ts/fdisk/align-512-512
new file mode 100755
index 00000000..70f0805e
--- /dev/null
+++ b/tests/ts/fdisk/align-512-512
@@ -0,0 +1,74 @@
+#!/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.
+#
+
+#
+# Test default 1MiB (2048 sectors) alignment for 512/512 disk *without*
+# topology.
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="align 512/512"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+DEVICE=$(ts_device_init 50)
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+n
+p
+3
+
++10M
+n
+e
+
+
+n
+
++5M
+n
+
++5M
+n
+
+
+p
+q
+EOF
+
+ts_device_deinit $DEVICE
+
+# remove disk ID
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/align-512-512-topology b/tests/ts/fdisk/align-512-512-topology
new file mode 100755
index 00000000..63801d23
--- /dev/null
+++ b/tests/ts/fdisk/align-512-512-topology
@@ -0,0 +1,91 @@
+#!/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.
+#
+
+
+#
+# Test alignment for 512/512 disk *with* topology -- aligned to optimal
+# I/O size (32KiB)
+#
+
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="align 512/512 +topology"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+modprobe --dry-run --quiet scsi_debug
+[ "$?" == 0 ] || ts_skip "missing scsi_debug module"
+
+rmmod scsi_debug &> /dev/null
+modprobe scsi_debug dev_size_mb=50 sector_size=512
+[ "$?" == 0 ] || ts_die "Cannot init device"
+
+sleep 3
+
+DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}')
+[ "x${DEVNAME}" == "x" ] && ts_die "Cannot found device"
+
+DEVICE="/dev/${DEVNAME}"
+
+ts_log "Create partitions"
+$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <<EOF
+c
+u
+n
+p
+1
+
++10M
+n
+p
+2
+
++10M
+n
+p
+3
+
++10M
+n
+e
+
+
+n
+
++5M
+n
+
++5M
+n
+
+
+p
+w
+q
+EOF
+
+ts_log "Alignment offsets:"
+cat /sys/block/${DEVNAME}/${DEVNAME}{1,2,3,4,5,6,7}/alignment_offset >> $TS_OUTPUT 2>&1
+
+sleep 3
+rmmod scsi_debug
+
+# remove disk ID
+sed -i -e 's/Disk identifier:.*//g' $TS_OUTPUT
+sed -i -e 's/Building a new.*//g' $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/fdisk/doslabel b/tests/ts/fdisk/doslabel
index a7c259ea..762cdaac 100755
--- a/tests/ts/fdisk/doslabel
+++ b/tests/ts/fdisk/doslabel
@@ -37,63 +37,63 @@ FDISK_CMD_DELETE_EXTENDED="d\n2\n" # delete second primary
ts_log "Initialize empty image"
TEST_IMAGE_NAME=$(ts_image_init 10)
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
# need to run init twice, to change system ID after new label, otherwise system
# ID will be random and will screw up md5's
ts_log "Create new DOS partition table"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CREATE_DOSLABEL}${FDISK_CMD_INIT}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create primary partition"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CREATE_PRIMARY}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Set partition type"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CHANGE_PARTTYPE}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Set primary partition active"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_SET_ACTIVE}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Re-create primary partition"
echo -e "${FDISK_CMD_INIT}d\n${FDISK_CMD_CREATE_PRIMARY}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create extended partition"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CREATE_EXTENDED}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create logical partitions"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CREATE_LOGICAL}${FDISK_CMD_CREATE_LOGICAL}${FDISK_CMD_CREATE_LOGICAL}${FDISK_CMD_CREATE_LOGICAL}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Delete logical partitions"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_DELETE_LOGICALS}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create another logical partition"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_CREATE_LOGICAL}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Delete primary partition"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_DELETE_PRIMARY}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Delete extended partition"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_DELETE_EXTENDED}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_finalize
diff --git a/tests/ts/fdisk/oddinput b/tests/ts/fdisk/oddinput
index c8698416..9d5c4762 100755
--- a/tests/ts/fdisk/oddinput
+++ b/tests/ts/fdisk/oddinput
@@ -24,7 +24,7 @@ ts_init "$*"
ts_log "Initialize empty image"
TEST_IMAGE_NAME=$(ts_image_init 10)
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Empty image listing" # this should report empty partition table
# TEST_IMAGE_NAME has absolute path, and is by definition different on each computer, we need to sed it away
diff --git a/tests/ts/fdisk/sunlabel b/tests/ts/fdisk/sunlabel
index 9c2b0188..6bf7e0ed 100755
--- a/tests/ts/fdisk/sunlabel
+++ b/tests/ts/fdisk/sunlabel
@@ -34,41 +34,41 @@ FDISK_CMD_CREATE_SECONDARY="n\n2\n128\n\n" # create secondary partition cylinder
ts_log "Initialize empty image"
TEST_IMAGE_NAME=$(ts_image_init 10)
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create new SUN partition table"
echo -e "${FDISK_CMD_INIT}${FDISK_CMD_DELETEALL}${FDISK_CMD_WRITE_CLOSE}" \
| $TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create first partition"
echo -e "${FDISK_CMD_CREATE_PRIMARY}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Set partition sysid"
echo -e "${FDISK_CMD_CHANGE_SYSID}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Set first partition readonly"
echo -e "${FDISK_CMD_TOGGLE_READONLY}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Set first partition mountable"
echo -e "${FDISK_CMD_TOGGLE_MOUNTABLE}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Create second partition"
echo -e "${FDISK_CMD_CREATE_SECONDARY}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_log "Delete all partitions"
echo -e "${FDISK_CMD_DELETEALL}${FDISK_CMD_WRITE_CLOSE}" | \
$TS_CMD_FDISK ${TEST_IMAGE_NAME} &> /dev/null
-ts_image_md5sum 2>&1 >> $TS_OUTPUT
+ts_image_md5sum >> $TS_OUTPUT 2>&1
ts_finalize
diff --git a/tests/ts/misc/strtosize b/tests/ts/misc/strtosize
new file mode 100755
index 00000000..41b45492
--- /dev/null
+++ b/tests/ts/misc/strtosize
@@ -0,0 +1,60 @@
+#!/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="strtosize"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+$TS_HELPER_STRTOSIZE -1 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 0 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 123 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 18446744073709551615 >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRTOSIZE 1K >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1KiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1M >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1MiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1G >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1GiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1T >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1TiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1P >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1PiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1E >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1EiB >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRTOSIZE 1KB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1MB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1GB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1TB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1PB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 1EB >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRTOSIZE "" >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE " " >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE " 1" >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE "1 " >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRTOSIZE 0x0a >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 0xff00 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRTOSIZE 0x80000000 >> $TS_OUTPUT 2>&1
+
+ts_finalize
+