summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--disk-utils/fdisk.84
-rw-r--r--disk-utils/fdisk.c7
-rw-r--r--disk-utils/sfdisk.89
-rw-r--r--disk-utils/sfdisk.c10
-rw-r--r--include/pt-mbr.h1
-rw-r--r--lib/sysfs.c2
-rw-r--r--libfdisk/docs/libfdisk-sections.txt6
-rw-r--r--libfdisk/src/context.c33
-rw-r--r--libfdisk/src/dos.c13
-rw-r--r--libfdisk/src/fdiskP.h4
-rw-r--r--libfdisk/src/gpt.c6
-rw-r--r--libfdisk/src/libfdisk.h.in2
-rw-r--r--libfdisk/src/libfdisk.sym2
-rw-r--r--libfdisk/src/partition.c3
-rw-r--r--libfdisk/src/sgi.c2
-rw-r--r--libfdisk/src/sun.c2
-rw-r--r--libfdisk/src/utils.c73
-rw-r--r--sys-utils/unshare.170
-rw-r--r--sys-utils/unshare.c161
-rw-r--r--tests/expected/sfdisk/dos-resize23
-rw-r--r--tests/expected/sfdisk/gpt-resize23
-rw-r--r--tests/functions.sh2
-rwxr-xr-xtests/ts/libmount/context50
-rwxr-xr-xtests/ts/libmount/context-py50
-rwxr-xr-xtests/ts/sfdisk/dos14
-rwxr-xr-xtests/ts/sfdisk/gpt15
26 files changed, 471 insertions, 116 deletions
diff --git a/disk-utils/fdisk.8 b/disk-utils/fdisk.8
index 1350d0257..fb298220e 100644
--- a/disk-utils/fdisk.8
+++ b/disk-utils/fdisk.8
@@ -53,6 +53,10 @@ to override the kernel's ideas.) Since util-linux-2.17, \fBfdisk\fR differentia
between logical and physical sector size. This option changes both sector sizes to
.IB sectorsize .
.TP
+\fB\-B\fR, \fB\-\-protect\-boot\fP
+Don't erase the begin of the first disk sector when create a new disk label. This
+feature is supported for GPT and MBR.
+.TP
\fB\-c\fR, \fB\-\-compatibility\fR[\fI=mode\fR]
Specify the compatibility mode, 'dos' or 'nondos'. The default is non-DOS
mode. For backward compatibility, it is possible to use the option without
diff --git a/disk-utils/fdisk.c b/disk-utils/fdisk.c
index 48c4d1734..a1e7259bf 100644
--- a/disk-utils/fdisk.c
+++ b/disk-utils/fdisk.c
@@ -680,6 +680,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
fputs(USAGE_OPTIONS, out);
fputs(_(" -b, --sector-size <size> physical and logical sector size\n"), out);
+ fputs(_(" -B, --protect-boot don't erase bootbits when creat a new label\n"), out);
fputs(_(" -c, --compatibility[=<mode>] mode is 'dos' or 'nondos' (default)\n"), out);
fputs(_(" -L, --color[=<when>] colorize output (auto, always or never)\n"), out);
fprintf(out,
@@ -737,6 +738,7 @@ int main(int argc, char **argv)
{ "units", optional_argument, NULL, 'u' },
{ "version", no_argument, NULL, 'V' },
{ "output", no_argument, NULL, 'o' },
+ { "protect-boot", no_argument, NULL, 'B' },
{ NULL, 0, NULL, 0 }
};
@@ -754,7 +756,7 @@ int main(int argc, char **argv)
fdisk_set_ask(cxt, ask_callback, NULL);
- while ((c = getopt_long(argc, argv, "b:c::C:hH:lL::o:sS:t:u::vV",
+ while ((c = getopt_long(argc, argv, "b:Bc::C:hH:lL::o:sS:t:u::vV",
longopts, NULL)) != -1) {
switch (c) {
case 'b':
@@ -766,6 +768,9 @@ int main(int argc, char **argv)
fdisk_save_user_sector_size(cxt, sz, sz);
break;
}
+ case 'B':
+ fdisk_enable_bootbits_protection(cxt, 1);
+ break;
case 'C':
fdisk_save_user_geometry(cxt,
strtou32_or_err(optarg,
diff --git a/disk-utils/sfdisk.8 b/disk-utils/sfdisk.8
index 18227591d..a7b84cab1 100644
--- a/disk-utils/sfdisk.8
+++ b/disk-utils/sfdisk.8
@@ -57,7 +57,14 @@ input format. If standard input is a terminal, then \fBsfdisk\fR starts an
interactive session.
.sp
If the option \fB\-N\fR is specified, then the changes are applied to
-the partition addressed by \fIpartition-number\fR.
+the partition addressed by \fIpartition-number\fR. The unspecified fields
+of the partition are not modified.
+.sp
+Note that it's possible to address unused partition by \fB\-N\fR. For example
+MBR always contains 4 partitions, but the number of the used partitions may be
+smaller. In this case sfdisk follows the default values from the partition
+table and it does not use built-in defaults for the unused partition specified
+by \fB\-N\fR. See also \fB\---append\fR.
.TP
.BR \-A , " \-\-activate \fIdevice\fR [" \fIpartition-number\fR...]
Switch on the bootable flag. If no \fIpartition-number\fR is specified,
diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c
index 6b60d040e..6645f5a39 100644
--- a/disk-utils/sfdisk.c
+++ b/disk-utils/sfdisk.c
@@ -206,6 +206,7 @@ static void sfdisk_init(struct sfdisk *sf)
if (!sf->cxt)
err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
fdisk_set_ask(sf->cxt, ask_callback, (void *) sf);
+ fdisk_enable_bootbits_protection(sf->cxt, 1);
if (sf->label_nested) {
struct fdisk_context *x = fdisk_new_nested_context(sf->cxt,
@@ -1161,16 +1162,21 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
*/
if (partno >= 0) {
size_t n;
+
if (!fdisk_has_label(sf->cxt))
errx(EXIT_FAILURE, _("%s: cannot modify partition %d: "
"no partition table was found"),
- devname, partno);
+ devname, partno + 1);
n = fdisk_get_npartitions(sf->cxt);
if ((size_t) partno > n)
errx(EXIT_FAILURE, _("%s: cannot modify partition %d: "
"partition table contains only %zu "
"partitions"),
- devname, partno, n);
+ devname, partno + 1, n);
+
+ if (!fdisk_is_partition_used(sf->cxt, partno))
+ fdisk_warnx(sf->cxt, _("warning: %s: partition %d is not defined yet"),
+ devname, partno + 1);
created = 1;
next_partno = partno;
}
diff --git a/include/pt-mbr.h b/include/pt-mbr.h
index fab65ea07..8c4f8e6a8 100644
--- a/include/pt-mbr.h
+++ b/include/pt-mbr.h
@@ -11,6 +11,7 @@ struct dos_partition {
} __attribute__((packed));
#define MBR_PT_OFFSET 0x1be
+#define MBR_PT_BOOTBITS_SIZE 440
static inline struct dos_partition *mbr_get_partition(unsigned char *mbr, int i)
{
diff --git a/lib/sysfs.c b/lib/sysfs.c
index ac3559619..1b2019112 100644
--- a/lib/sysfs.c
+++ b/lib/sysfs.c
@@ -246,7 +246,7 @@ DIR *sysfs_opendir(struct sysfs_cxt *cxt, const char *attr)
* -- we cannot use cxt->sysfs_fd directly, because closedir()
* will close this our persistent file descriptor.
*/
- fd = dup(cxt->dir_fd);
+ fd = fcntl(cxt->dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
if (fd < 0)
return NULL;
diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt
index 8713d23b3..339c15cd3 100644
--- a/libfdisk/docs/libfdisk-sections.txt
+++ b/libfdisk/docs/libfdisk-sections.txt
@@ -282,6 +282,7 @@ fdisk_unref_table
fdisk_context
fdisk_assign_device
fdisk_deassign_device
+fdisk_enable_bootbits_protection
fdisk_enable_details
fdisk_enable_listonly
fdisk_get_alignment_offset
@@ -300,22 +301,23 @@ fdisk_get_parent
fdisk_get_physector_size
fdisk_get_sector_size
fdisk_get_size_unit
-FDISK_PLURAL
-FDISK_SINGULAR
fdisk_get_unit
fdisk_get_units_per_sector
fdisk_has_label
+fdisk_has_protected_bootbits
fdisk_is_details
fdisk_is_labeltype
fdisk_is_listonly
fdisk_is_readonly
fdisk_new_context
fdisk_new_nested_context
+FDISK_PLURAL
fdisk_ref_context
fdisk_set_first_lba
fdisk_set_last_lba
fdisk_set_size_unit
fdisk_set_unit
+FDISK_SINGULAR
fdisk_unref_context
fdisk_use_cylinders
</SECTION>
diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c
index 84867b0ab..efc961cf7 100644
--- a/libfdisk/src/context.c
+++ b/libfdisk/src/context.c
@@ -94,12 +94,13 @@ static int init_nested_from_parent(struct fdisk_context *cxt, int isnew)
cxt->user_log_sector = parent->user_log_sector;
cxt->user_pyh_sector = parent->user_pyh_sector;
- /* parent <--> nested independent setting, initialize for new nested
+ /* parent <--> nested independent setting, initialize for new nested
* contexts only */
if (isnew) {
cxt->listonly = parent->listonly;
cxt->display_details = parent->display_details;
cxt->display_in_cyl_units = parent->display_in_cyl_units;
+ cxt->protect_bootbits = parent->protect_bootbits;
}
free(cxt->dev_path);
@@ -304,6 +305,36 @@ int fdisk_has_label(struct fdisk_context *cxt)
}
/**
+ * fdisk_has_protected_bootbits:
+ * @cxt: fdisk context
+ *
+ * Returns: return 1 if boot bits protection enabled.
+ */
+int fdisk_has_protected_bootbits(struct fdisk_context *cxt)
+{
+ return cxt && cxt->protect_bootbits;
+}
+
+/**
+ * fdisk_enable_bootbits_protection:
+ * @cxt: fdisk context
+ * @enable: 1 or 0
+ *
+ * The library zeroizes all the first sector when create a new disk label by
+ * default. This function allows to control this behavior. For now it's
+ * supported for MBR and GPT.
+ *
+ * Returns: 0 on success, < 0 on error.
+ */
+int fdisk_enable_bootbits_protection(struct fdisk_context *cxt, int enable)
+{
+ if (!cxt)
+ return -EINVAL;
+ cxt->protect_bootbits = enable ? 1 : 0;
+ return 0;
+}
+
+/**
* fdisk_get_npartitions:
* @cxt: context
*
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index dce9829eb..f2308e3e0 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -659,7 +659,10 @@ static int dos_create_disklabel(struct fdisk_context *cxt)
if (!has_id)
random_get_bytes(&id, sizeof(id));
- rc = fdisk_init_firstsector_buffer(cxt);
+ if (fdisk_has_protected_bootbits(cxt))
+ rc = fdisk_init_firstsector_buffer(cxt, 0, MBR_PT_BOOTBITS_SIZE);
+ else
+ rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
if (rc)
return rc;
dos_init(cxt);
@@ -1221,7 +1224,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
}
}
- set_partition(cxt, n, 0, start, stop, sys, pa && pa->boot == 1 ? 1 : 0);
+ set_partition(cxt, n, 0, start, stop, sys, fdisk_partition_is_bootable(pa));
if (n > 4) {
struct pte *pe = self_pte(cxt, n);
set_partition(cxt, n - 1, 1, pe->offset, stop,
@@ -1963,13 +1966,15 @@ static int dos_set_partition(struct fdisk_context *cxt, size_t n,
set_partition(cxt, n, 0, start, start + size - 1,
pa->type ? pa->type->code : p->sys_ind,
- pa->boot == 1);
+ FDISK_IS_UNDEF(pa->boot) ?
+ p->boot_ind == ACTIVE_FLAG :
+ fdisk_partition_is_bootable(pa));
} else {
DBG(LABEL, ul_debug("DOS: keep size, modify properties"));
if (pa->type)
p->sys_ind = pa->type->code;
if (!FDISK_IS_UNDEF(pa->boot))
- p->boot_ind = pa->boot == 1 ? ACTIVE_FLAG : 0;
+ p->boot_ind = fdisk_partition_is_bootable(pa) ? ACTIVE_FLAG : 0;
}
partition_set_changed(cxt, n, 1);
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index dc561f389..0ca498d54 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -350,6 +350,7 @@ struct fdisk_context {
unsigned int readonly : 1, /* don't write to the device */
display_in_cyl_units : 1, /* for obscure labels */
display_details : 1, /* expert display mode */
+ protect_bootbits : 1, /* don't zeroize fll irst sector */
listonly : 1; /* list partition, nothing else */
int sizeunit; /* SIZE fields, FDISK_SIZEUNIT_* */
@@ -402,7 +403,8 @@ extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt);
extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt);
/* utils.c */
-extern int fdisk_init_firstsector_buffer(struct fdisk_context *cxt);
+extern int fdisk_init_firstsector_buffer(struct fdisk_context *cxt,
+ unsigned int protect_off, unsigned int protect_size);
extern int fdisk_read_firstsector(struct fdisk_context *cxt);
extern char *fdisk_partname(const char *dev, size_t partno);
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 9ceb01a6e..62271c115 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -27,6 +27,7 @@
#include "bitops.h"
#include "strutils.h"
#include "all-io.h"
+#include "pt-mbr.h"
/**
* SECTION: gpt
@@ -406,7 +407,10 @@ static int gpt_mknew_pmbr(struct fdisk_context *cxt)
if (!cxt || !cxt->firstsector)
return -ENOSYS;
- rc = fdisk_init_firstsector_buffer(cxt);
+ if (fdisk_has_protected_bootbits(cxt))
+ rc = fdisk_init_firstsector_buffer(cxt, 0, MBR_PT_BOOTBITS_SIZE);
+ else
+ rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
if (rc)
return rc;
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index a38ef47c9..5a14c26f1 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -211,6 +211,8 @@ enum {
int fdisk_set_size_unit(struct fdisk_context *cxt, int unit);
int fdisk_get_size_unit(struct fdisk_context *cxt);
+int fdisk_has_protected_bootbits(struct fdisk_context *cxt);
+int fdisk_enable_bootbits_protection(struct fdisk_context *cxt, int enable);
/* parttype.c */
struct fdisk_parttype *fdisk_new_parttype(void);
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index 5ff270b59..4d8276eca 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -244,4 +244,6 @@ FDISK_2.27 {
fdisk_script_set_fgets;
fdisk_script_set_userdata;
fdisk_script_get_userdata;
+ fdisk_enable_bootbits_protection;
+ fdisk_has_protected_bootbits;
} FDISK_2.26;
diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c
index 640cd5a1d..114cac56e 100644
--- a/libfdisk/src/partition.c
+++ b/libfdisk/src/partition.c
@@ -757,8 +757,7 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
}
break;
case FDISK_FIELD_BOOT:
- if (fdisk_partition_is_bootable(pa))
- rc = asprintf(&p, "%c", pa->boot ? '*' : ' ');
+ p = fdisk_partition_is_bootable(pa) ? strdup("*") : NULL;
break;
case FDISK_FIELD_START:
if (fdisk_partition_has_start(pa)) {
diff --git a/libfdisk/src/sgi.c b/libfdisk/src/sgi.c
index cd4cedff0..7cc68b501 100644
--- a/libfdisk/src/sgi.c
+++ b/libfdisk/src/sgi.c
@@ -965,7 +965,7 @@ static int sgi_create_disklabel(struct fdisk_context *cxt)
}
}
#endif
- rc = fdisk_init_firstsector_buffer(cxt);
+ rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
if (rc)
return rc;
diff --git a/libfdisk/src/sun.c b/libfdisk/src/sun.c
index d99c39f6f..27e3bdd00 100644
--- a/libfdisk/src/sun.c
+++ b/libfdisk/src/sun.c
@@ -209,7 +209,7 @@ static int sun_create_disklabel(struct fdisk_context *cxt)
assert(fdisk_is_label(cxt, SUN));
/* map first sector to header */
- rc = fdisk_init_firstsector_buffer(cxt);
+ rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
if (rc)
return rc;
diff --git a/libfdisk/src/utils.c b/libfdisk/src/utils.c
index 482a3062d..cc470d99b 100644
--- a/libfdisk/src/utils.c
+++ b/libfdisk/src/utils.c
@@ -10,14 +10,49 @@
* @short_description: misc fdisk functions
*/
+static int read_from_device(struct fdisk_context *cxt,
+ unsigned char *buf,
+ uintmax_t start, size_t size)
+{
+ ssize_t r;
+
+ assert(cxt);
+
+ DBG(CXT, ul_debugobj(cxt, "reading: offset=%ju, size=%zu",
+ start, size));
+
+ r = lseek(cxt->dev_fd, start, SEEK_SET);
+ if (r == -1)
+ {
+ DBG(CXT, ul_debugobj(cxt, "failed to seek to offset %ju: %m", start));
+ return -errno;
+ }
+
+ r = read(cxt->dev_fd, buf, size);
+ if (r < 0 || r != size) {
+ if (!errno)
+ errno = EINVAL; /* probably too small file/device */
+ DBG(CXT, ul_debugobj(cxt, "failed to read %zu from offset %ju: %m",
+ size, start));
+ return -errno;
+ }
+
+ return 0;
+}
+
+
/*
* Zeros in-memory first sector buffer
*/
-int fdisk_init_firstsector_buffer(struct fdisk_context *cxt)
+int fdisk_init_firstsector_buffer(struct fdisk_context *cxt,
+ unsigned int protect_off,
+ unsigned int protect_size)
{
if (!cxt)
return -EINVAL;
+ assert(protect_off + protect_size <= cxt->sector_size);
+
if (!cxt->firstsector || cxt->firstsector_bufsz != cxt->sector_size) {
/* Let's allocate a new buffer if no allocated yet, or the
* current buffer has incorrect size */
@@ -36,43 +71,37 @@ int fdisk_init_firstsector_buffer(struct fdisk_context *cxt)
DBG(CXT, ul_debugobj(cxt, "zeroize in-memory first sector buffer"));
memset(cxt->firstsector, 0, cxt->firstsector_bufsz);
+
+ if (protect_size) {
+ /*
+ * It would be possible to reuse data from cxt->firstsector
+ * (call memset() for non-protected area only) and avoid one
+ * read() from the device, but it seems like a too fragile
+ * solution as we have no clue about stuff in the buffer --
+ * maybe it was already modified. Let's re-read from the device
+ * to be sure. -- kzak 13-Apr-2015
+ */
+ DBG(CXT, ul_debugobj(cxt, "first sector protection enabled -- re-reading"));
+ read_from_device(cxt, cxt->firstsector, protect_off, protect_size);
+ }
return 0;
}
int fdisk_read_firstsector(struct fdisk_context *cxt)
{
- ssize_t r;
int rc;
assert(cxt);
assert(cxt->sector_size);
- rc = fdisk_init_firstsector_buffer(cxt);
+ rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
if (rc)
return rc;
assert(cxt->sector_size == cxt->firstsector_bufsz);
- DBG(CXT, ul_debugobj(cxt, "reading first sector "
- "buffer [sector_size=%lu]", cxt->sector_size));
-
- r = lseek(cxt->dev_fd, 0, SEEK_SET);
- if (r == -1)
- {
- DBG(CXT, ul_debugobj(cxt, "failed to seek to first sector %m"));
- return -errno;
- }
-
- r = read(cxt->dev_fd, cxt->firstsector, cxt->sector_size);
- if (r != cxt->sector_size) {
- if (!errno)
- errno = EINVAL; /* probably too small file/device */
- DBG(CXT, ul_debugobj(cxt, "failed to read first sector %m"));
- return -errno;
- }
-
- return 0;
+ return read_from_device(cxt, cxt->firstsector, 0, cxt->sector_size);
}
/**
diff --git a/sys-utils/unshare.1 b/sys-utils/unshare.1
index 6fc71f4f7..14755e728 100644
--- a/sys-utils/unshare.1
+++ b/sys-utils/unshare.1
@@ -8,8 +8,17 @@ unshare \- run program with some namespaces unshared from parent
.RI [ arguments ]
.SH DESCRIPTION
Unshares the indicated namespaces from the parent process and then executes
-the specified \fIprogram\fR. The namespaces to be unshared are indicated via
-options. Unshareable namespaces are:
+the specified \fIprogram\fR.
+.PP
+The namespaces can optionally be persisted by bind mounting /proc/[pid]/ns/[type] files
+to a filesystem path and entered with
+.BR nsenter (1)
+even after \fIprogram\fR terminates.
+Once a persistent namespace is no longer needed it can be unpersisted with
+.BR umount (8).
+See EXAMPLES section for more details.
+.PP
+The namespaces to be unshared are indicated via options. Unshareable namespaces are:
.TP
.BR "mount namespace"
Mounting and unmounting filesystems will not affect the rest of the system
@@ -47,24 +56,29 @@ The process will have a distinct set of UIDs, GIDs and capabilities.
See \fBclone\fR(2) for the exact semantics of the flags.
.SH OPTIONS
.TP
-.BR \-i , " \-\-ipc"
-Unshare the IPC namespace.
+.BR \-i , " \-\-ipc"[=\fIfile\fP]
+Unshare the IPC namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
.TP
-.BR \-m , " \-\-mount"
-Unshare the mount namespace.
+.BR \-m , " \-\-mount"[=\fIfile\fP]
+Unshare the mount namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
.TP
-.BR \-n , " \-\-net"
-Unshare the network namespace.
+.BR \-n , " \-\-net"[=\fIfile\fP]
+Unshare the network namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
.TP
-.BR \-p , " \-\-pid"
-Unshare the pid namespace.
-See also the \fB--fork\fP and \fB--mount-proc\fP options.
+.BR \-p , " \-\-pid"[=\fIfile\fP]
+Unshare the pid namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount. See also the \fB--fork\fP and \fB--mount-proc\fP options.
.TP
-.BR \-u , " \-\-uts"
-Unshare the UTS namespace.
+.BR \-u , " \-\-uts"[=\fIfile\fP]
+Unshare the UTS namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
.TP
-.BR \-U , " \-\-user"
-Unshare the user namespace.
+.BR \-U , " \-\-user"[=\fIfile\fP]
+Unshare the user namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
.TP
.BR \-f , " \-\-fork"
Fork the specified \fIprogram\fR as a child process of \fBunshare\fR rather than
@@ -125,14 +139,32 @@ procfs instance.
root
.br
Establish a user namespace as an unprivileged user with a root user within it.
+.TP
+.TQ
+.B # touch /root/uts-ns
+.TQ
+.B # unshare --uts=/root/uts-ns hostanme FOO
+.TQ
+.B # nsenter --uts=/root/uts-ns hostname
+.TQ
+FOO
+.TQ
+.B # umount /root/uts-ns
+.br
+Establish a persistent UTS namespace, modify hostname. The namespace maybe later entered
+by nsenter. The namespace is destroyed by umount the bind reference.
.SH SEE ALSO
.BR unshare (2),
.BR clone (2),
.BR mount (8)
-.SH BUGS
-None known so far.
-.SH AUTHOR
-Mikhail Gusarov <dottedmag@dottedmag.net>
+.SH AUTHORS
+.UR dottedmag@dottedmag.net
+Mikhail Gusarov
+.UE
+.br
+.UR kzak@redhat.com
+Karel Zak
+.UE
.SH AVAILABILITY
The unshare command is part of the util-linux package and is available from
ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index 18a7c7bda..460d149a1 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -27,6 +27,10 @@
#include <sys/wait.h>
#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
/* we only need some defines missing in sys/mount.h, no libmount linkage */
#include <libmount.h>
@@ -42,6 +46,24 @@
/* 'private' is kernel default */
#define UNSHARE_PROPAGATION_DEFAULT (MS_REC | MS_PRIVATE)
+/* /proc namespace files and mountpoints for binds */
+static struct namespace_file {
+ int type; /* CLONE_NEW* */
+ const char *name; /* ns/<type> */
+ const char *target; /* user specified target for bind mount */
+} namespace_files[] = {
+ { .type = CLONE_NEWUSER, .name = "ns/user" },
+ { .type = CLONE_NEWIPC, .name = "ns/ipc" },
+ { .type = CLONE_NEWUTS, .name = "ns/uts" },
+ { .type = CLONE_NEWNET, .name = "ns/net" },
+ { .type = CLONE_NEWPID, .name = "ns/pid" },
+ { .type = CLONE_NEWNS, .name = "ns/mnt" },
+ { .name = NULL }
+};
+
+static int npersists; /* number of persistent namespaces */
+
+
enum {
SETGROUPS_NONE = -1,
SETGROUPS_DENY = 0,
@@ -133,6 +155,77 @@ static void set_propagation(unsigned long flags)
err(EXIT_FAILURE, _("cannot change root filesystem propagation"));
}
+
+static int set_ns_target(int type, const char *path)
+{
+ struct namespace_file *ns;
+
+ for (ns = namespace_files; ns->name; ns++) {
+ if (ns->type != type)
+ continue;
+ ns->target = path;
+ npersists++;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int bind_ns_files(pid_t pid)
+{
+ struct namespace_file *ns;
+ char src[PATH_MAX];
+
+ for (ns = namespace_files; ns->name; ns++) {
+ if (!ns->target)
+ continue;
+
+ snprintf(src, sizeof(src), "/proc/%u/%s", (unsigned) pid, ns->name);
+
+ if (mount(src, ns->target, NULL, MS_BIND, NULL) != 0)
+ err(EXIT_FAILURE, _("mount %s on %s failed"), src, ns->target);
+ }
+
+ return 0;
+}
+
+static ino_t get_mnt_ino(pid_t pid)
+{
+ struct stat st;
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "/proc/%u/ns/mnt", (unsigned) pid);
+
+ if (stat(path, &st) != 0)
+ err(EXIT_FAILURE, _("cannot stat %s"), path);
+ return st.st_ino;
+}
+
+static void bind_ns_files_from_child(pid_t *child)
+{
+ pid_t ppid = getpid();
+ ino_t ino = get_mnt_ino(ppid);
+
+ *child = fork();
+
+ switch(*child) {
+ case -1:
+ err(EXIT_FAILURE, _("fork failed"));
+ case 0: /* child */
+ do {
+ /* wait until parent unshare() */
+ ino_t new_ino = get_mnt_ino(ppid);
+ if (ino != new_ino)
+ break;
+ } while (1);
+ bind_ns_files(ppid);
+ exit(EXIT_SUCCESS);
+ break;
+ default: /* parent */
+ break;
+ }
+}
+
static void usage(int status)
{
FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
@@ -145,12 +238,12 @@ static void usage(int status)
fputs(_("Run a program with some namespaces unshared from the parent.\n"), out);
fputs(USAGE_OPTIONS, out);
- fputs(_(" -m, --mount unshare mounts namespace\n"), out);
- fputs(_(" -u, --uts unshare UTS namespace (hostname etc)\n"), out);
- fputs(_(" -i, --ipc unshare System V IPC namespace\n"), out);
- fputs(_(" -n, --net unshare network namespace\n"), out);
- fputs(_(" -p, --pid unshare pid namespace\n"), out);
- fputs(_(" -U, --user unshare user namespace\n"), out);
+ fputs(_(" -m, --mount[=<file>] unshare mounts namespace\n"), out);
+ fputs(_(" -u, --uts[=<file>] unshare UTS namespace (hostname etc)\n"), out);
+ fputs(_(" -i, --ipc[=<file>] unshare System V IPC namespace\n"), out);
+ fputs(_(" -n, --net[=<file>] unshare network namespace\n"), out);
+ fputs(_(" -p, --pid[=<file>] unshare pid namespace\n"), out);
+ fputs(_(" -U, --user[=<file>] unshare user namespace\n"), out);
fputs(_(" -f, --fork fork before launching <program>\n"), out);
fputs(_(" --mount-proc[=<dir>] mount proc filesystem first (implies --mount)\n"), out);
fputs(_(" -r, --map-root-user map current user to root (implies --user)\n"), out);
@@ -176,12 +269,14 @@ int main(int argc, char *argv[])
static const struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'V'},
- { "mount", no_argument, 0, 'm' },
- { "uts", no_argument, 0, 'u' },
- { "ipc", no_argument, 0, 'i' },
- { "net", no_argument, 0, 'n' },
- { "pid", no_argument, 0, 'p' },
- { "user", no_argument, 0, 'U' },
+
+ { "mount", optional_argument, 0, 'm' },
+ { "uts", optional_argument, 0, 'u' },
+ { "ipc", optional_argument, 0, 'i' },
+ { "net", optional_argument, 0, 'n' },
+ { "pid", optional_argument, 0, 'p' },
+ { "user", optional_argument, 0, 'U' },
+
{ "fork", no_argument, 0, 'f' },
{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
{ "map-root-user", no_argument, 0, 'r' },
@@ -194,6 +289,8 @@ int main(int argc, char *argv[])
int unshare_flags = 0;
int c, forkit = 0, maproot = 0;
const char *procmnt = NULL;
+ pid_t pid = 0;
+ int status;
unsigned long propagation = UNSHARE_PROPAGATION_DEFAULT;
uid_t real_euid = geteuid();
gid_t real_egid = getegid();;
@@ -215,21 +312,33 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS;
case 'm':
unshare_flags |= CLONE_NEWNS;
+ if (optarg)
+ set_ns_target(CLONE_NEWNS, optarg);
break;
case 'u':
unshare_flags |= CLONE_NEWUTS;
+ if (optarg)
+ set_ns_target(CLONE_NEWUTS, optarg);
break;
case 'i':
unshare_flags |= CLONE_NEWIPC;
+ if (optarg)
+ set_ns_target(CLONE_NEWIPC, optarg);
break;
case 'n':
unshare_flags |= CLONE_NEWNET;
+ if (optarg)
+ set_ns_target(CLONE_NEWNET, optarg);
break;
case 'p':
unshare_flags |= CLONE_NEWPID;
+ if (optarg)
+ set_ns_target(CLONE_NEWPID, optarg);
break;
case 'U':
unshare_flags |= CLONE_NEWUSER;
+ if (optarg)
+ set_ns_target(CLONE_NEWUSER, optarg);
break;
case OPT_MOUNTPROC:
unshare_flags |= CLONE_NEWNS;
@@ -250,12 +359,35 @@ int main(int argc, char *argv[])
}
}
+ if (npersists && (unshare_flags & CLONE_NEWNS))
+ bind_ns_files_from_child(&pid);
+
if (-1 == unshare(unshare_flags))
err(EXIT_FAILURE, _("unshare failed"));
+ if (npersists) {
+ if (pid && (unshare_flags & CLONE_NEWNS)) {
+ /* wait for bind_ns_files_from_child() */
+ int rc;
+
+ do {
+ rc = waitpid(pid, &status, 0);
+ if (rc < 0) {
+ if (errno == EINTR)
+ continue;
+ err(EXIT_FAILURE, _("waitpid failed"));
+ }
+ if (WIFEXITED(status) &&
+ WEXITSTATUS(status) != EXIT_SUCCESS)
+ return WEXITSTATUS(status);
+ } while (rc < 0);
+ } else
+ /* simple way, just bind */
+ bind_ns_files(getpid());
+ }
+
if (forkit) {
- int status;
- pid_t pid = fork();
+ pid = fork();
switch(pid) {
case -1:
@@ -273,6 +405,7 @@ int main(int argc, char *argv[])
}
}
+
if (maproot) {
if (setgrpcmd == SETGROUPS_ALLOW)
errx(EXIT_FAILURE, _("options --setgroups=allow and "
diff --git a/tests/expected/sfdisk/dos-resize b/tests/expected/sfdisk/dos-resize
new file mode 100644
index 000000000..3ce02ec46
--- /dev/null
+++ b/tests/expected/sfdisk/dos-resize
@@ -0,0 +1,23 @@
+Checking that no-one is using this disk right now ... OK
+
+Disk <removed>: 50 MiB, 52428800 bytes, 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
+Disklabel type: dos
+Disk identifier: <removed>
+
+Old situation:
+
+Device Boot Start End Sectors Size Id Type
+<removed>1 * 2048 22527 20480 10M 82 Linux swap / Solaris
+
+<removed>1:
+New situation:
+
+Device Boot Start End Sectors Size Id Type
+<removed>1 * 2048 102399 100352 49M 82 Linux swap / Solaris
+
+The partition table has been altered.
+Calling ioctl() to re-read partition table.
+Syncing disks.
diff --git a/tests/expected/sfdisk/gpt-resize b/tests/expected/sfdisk/gpt-resize
new file mode 100644
index 000000000..dbe41ba61
--- /dev/null
+++ b/tests/expected/sfdisk/gpt-resize
@@ -0,0 +1,23 @@
+Checking that no-one is using this disk right now ... OK
+
+Disk <removed>: 50 MiB, 52428800 bytes, 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
+Disklabel type: gpt
+Disk identifier: <removed>
+
+Old situation:
+
+Device Start End Sectors Size Type
+<removed>1 2048 22527 20480 10M Linux swap
+
+<removed>1:
+New situation:
+
+Device Start End Sectors Size Type
+<removed>1 2048 102366 100319 49M Linux swap
+
+The partition table has been altered.
+Calling ioctl() to re-read partition table.
+Syncing disks.
diff --git a/tests/functions.sh b/tests/functions.sh
index 44e087cdb..6f786e797 100644
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -545,7 +545,7 @@ function ts_is_mounted {
grep -q $DEV /proc/mounts && return 0
if [ "${DEV#/dev/loop/}" != "$DEV" ]; then
- return grep -q "/dev/loop${DEV#/dev/loop/}" /proc/mounts
+ grep -q "/dev/loop${DEV#/dev/loop/}" /proc/mounts && return 0
fi
return 1
}
diff --git a/tests/ts/libmount/context b/tests/ts/libmount/context
index 7acfb9cdf..6de160bea 100755
--- a/tests/ts/libmount/context
+++ b/tests/ts/libmount/context
@@ -34,6 +34,11 @@ umount $MOUNTPOINT &> /dev/null
ts_scsi_debug_init dev_size_mb=100
DEVNAME=$(basename $TS_DEVICE)
+grep -q '#define USE_LIBMOUNT_FORCE_MOUNTINFO' ${TS_TOPDIR}/../config.h
+if [ $? == 0 ]; then
+ MOUNTINFO_ONLY=yes
+fi
+
ts_log "Create partitions"
$TS_CMD_FDISK ${TS_DEVICE} &> /dev/null <<EOF
n
@@ -64,47 +69,53 @@ ts_log "Do tests..."
export LIBMOUNT_MTAB=$TS_OUTPUT.mtab
> $LIBMOUNT_MTAB
+# check local mtab of system mountinfo
+function is_mounted {
+ if [ "$MOUNTINFO_ONLY" = "yes" ]; then
+ ts_is_mounted "$1"
+ return $?
+ fi
+ grep -q "$1" $LIBMOUNT_MTAB && return 0
+ return 1
+}
+
+
udevadm settle
ts_device_has "TYPE" "ext4" $DEVICE || ts_die "Cannot find ext3 on $DEVICE" $DEVICE
+
ts_init_subtest "mount-by-devname"
mkdir -p $MOUNTPOINT &> /dev/null
ts_valgrind $TESTPROG --mount $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>&1
-
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by device) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
+
ts_init_subtest "umount-by-devname"
ts_valgrind $TESTPROG --umount $DEVICE >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount (device) failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "mount-by-label"
mkdir -p $MOUNTPOINT &> /dev/null
ts_valgrind $TESTPROG --mount LABEL="$LABEL" $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by label) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "umount-by-mountpoint"
ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB && \
- echo "umount (mountpoint) failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "mount-by-uuid"
mkdir -p $MOUNTPOINT &> /dev/null
ts_valgrind $TESTPROG --mount UUID="$UUID" $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by uuid) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
@@ -112,15 +123,13 @@ ts_init_subtest "mount-flags"
mkdir -p $MOUNTPOINT &> /dev/null
ts_valgrind $TESTPROG --mount -o ro,noexec,nosuid,strictatime $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>&1
$TS_CMD_FINDMNT --kernel $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_valgrind $TESTPROG --mount -o remount,rw $MOUNTPOINT >> $TS_OUTPUT 2>&1
$TS_CMD_FINDMNT --kernel $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>&1
ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
@@ -131,14 +140,13 @@ mkfs.ext3 -F $img &> /dev/null
udevadm settle
ts_valgrind $TESTPROG --mount -o loop $img $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $MOUNTPOINT $LIBMOUNT_MTAB || \
- echo "(loopdev) cannot find $MOUNTPOINT in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $MOUNTPOINT || echo "$MOUNTPOINT not mounted" >> $TS_OUTPUT 2>&1
udevadm settle
ts_valgrind $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $MOUNTPOINT $LIBMOUNT_MTAB &&
- echo "umount failed: found $MOUNTPOINT in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $MOUNTPOINT && echo "$MOUNTPOINT still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
+
ts_init_subtest "x-mount.mkdir"
$TS_CMD_MOUNT -o x-mount.mkdir --bind $MOUNTPOINT $TS_NOEXIST >> $TS_OUTPUT 2>&1 &&
echo "successfully mounted" >> $TS_OUTPUT
diff --git a/tests/ts/libmount/context-py b/tests/ts/libmount/context-py
index b2355a795..4db2ac12d 100755
--- a/tests/ts/libmount/context-py
+++ b/tests/ts/libmount/context-py
@@ -36,6 +36,11 @@ umount $MOUNTPOINT &> /dev/null
ts_scsi_debug_init dev_size_mb=100
DEVNAME=$(basename $TS_DEVICE)
+grep -q '#define USE_LIBMOUNT_FORCE_MOUNTINFO' ${TS_TOPDIR}/../config.h
+if [ $? == 0 ]; then
+ MOUNTINFO_ONLY=yes
+fi
+
ts_log "Create partitions"
$TS_CMD_FDISK ${TS_DEVICE} &> /dev/null <<EOF
n
@@ -66,47 +71,53 @@ ts_log "Do tests..."
export LIBMOUNT_MTAB=$TS_OUTPUT.mtab
> $LIBMOUNT_MTAB
+# check local mtab of system mountinfo
+function is_mounted {
+ if [ "$MOUNTINFO_ONLY" = "yes" ]; then
+ ts_is_mounted "$1"
+ return $?
+ fi
+ grep -q "$1" $LIBMOUNT_MTAB && return 0
+ return 1
+}
+
+
udevadm settle
ts_device_has "TYPE" "ext4" $DEVICE || ts_die "Cannot find ext3 on $DEVICE" $DEVICE
+
ts_init_subtest "mount-by-devname"
mkdir -p $MOUNTPOINT &> /dev/null
$PYTHON $TESTPROG --mount $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>&1
-
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by device) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
+
ts_init_subtest "umount-by-devname"
$PYTHON $TESTPROG --umount $DEVICE >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount (device) failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "mount-by-label"
mkdir -p $MOUNTPOINT &> /dev/null
$PYTHON $TESTPROG --mount LABEL="$LABEL" $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by label) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "umount-by-mountpoint"
$PYTHON $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB && \
- echo "umount (mountpoint) failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "mount-by-uuid"
mkdir -p $MOUNTPOINT &> /dev/null
$PYTHON $TESTPROG --mount UUID="$UUID" $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "(by uuid) cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
$PYTHON $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
@@ -114,15 +125,13 @@ ts_init_subtest "mount-flags"
mkdir -p $MOUNTPOINT &> /dev/null
$PYTHON $TESTPROG --mount -o ro,noexec,nosuid,strictatime $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>&1
$TS_CMD_FINDMNT --kernel $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB || \
- echo "cannot find $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>&1
$PYTHON $TESTPROG --mount -o remount,rw $MOUNTPOINT >> $TS_OUTPUT 2>&1
$TS_CMD_FINDMNT --kernel $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>&1
$PYTHON $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $DEVICE $LIBMOUNT_MTAB &&
- echo "umount failed: found $DEVICE in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
@@ -133,12 +142,10 @@ mkfs.ext3 -F $img &> /dev/null
udevadm settle
$PYTHON $TESTPROG --mount -o loop $img $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $MOUNTPOINT $LIBMOUNT_MTAB || \
- echo "(loopdev) cannot find $MOUNTPOINT in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $MOUNTPOINT || echo "$MOUNTPOINT not mounted" >> $TS_OUTPUT 2>&1
udevadm settle
$PYTHON $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>&1
-grep -q $MOUNTPOINT $LIBMOUNT_MTAB &&
- echo "umount failed: found $MOUNTPOINT in $LIBMOUNT_MTAB" >> $TS_OUTPUT 2>&1
+is_mounted $MOUNTPOINT && echo "$MOUNTPOINT still mounted" >> $TS_OUTPUT 2>&1
ts_finalize_subtest
ts_init_subtest "x-mount.mkdir"
@@ -146,6 +153,7 @@ $TS_CMD_MOUNT -o x-mount.mkdir --bind $MOUNTPOINT $TS_NOEXIST >> $TS_OUTPUT 2>&1
echo "successfully mounted" >> $TS_OUTPUT
ts_finalize_subtest
+
$TS_CMD_UMOUNT $TS_NOEXIST
rmdir $TS_NOEXIST
diff --git a/tests/ts/sfdisk/dos b/tests/ts/sfdisk/dos
index 899e93c72..8277ddcfa 100755
--- a/tests/ts/sfdisk/dos
+++ b/tests/ts/sfdisk/dos
@@ -111,5 +111,19 @@ udevadm settle
ts_finalize_subtest
+ts_init_subtest "resize"
+$TS_CMD_WIPEFS -a ${TS_DEVICE} &> /dev/null
+udevadm settle
+$TS_CMD_SFDISK ${TS_DEVICE} > /dev/null 2>&1 <<EOF
+label: dos
+,10M,S,*
+EOF
+udevadm settle
+echo ',+' | $TS_CMD_SFDISK -N1 ${TS_DEVICE} >> $TS_OUTPUT 2>&1
+ts_fdisk_clean $TS_DEVICE
+udevadm settle
+ts_finalize_subtest
+
+
rmmod scsi_debug
ts_finalize
diff --git a/tests/ts/sfdisk/gpt b/tests/ts/sfdisk/gpt
index 19269b33b..252691f46 100755
--- a/tests/ts/sfdisk/gpt
+++ b/tests/ts/sfdisk/gpt
@@ -22,6 +22,7 @@ TS_DESC="GPT"
ts_init "$*"
ts_check_test_command "$TS_CMD_FDISK"
+ts_check_test_command "$TS_CMD_WIPEFS"
ts_skip_nonroot
@@ -109,5 +110,19 @@ ts_fdisk_clean $TS_DEVICE
ts_finalize_subtest
+ts_init_subtest "resize"
+$TS_CMD_WIPEFS -a ${TS_DEVICE} &> /dev/null
+udevadm settle
+$TS_CMD_SFDISK ${TS_DEVICE} > /dev/null 2>&1 <<EOF
+label: gpt
+,10M,S,*
+EOF
+udevadm settle
+echo ',+' | $TS_CMD_SFDISK -N1 ${TS_DEVICE} >> $TS_OUTPUT 2>&1
+ts_fdisk_clean $TS_DEVICE
+udevadm settle
+ts_finalize_subtest
+
+
rmmod scsi_debug
ts_finalize