diff options
-rw-r--r-- | disk-utils/fdisk.8 | 4 | ||||
-rw-r--r-- | disk-utils/fdisk.c | 7 | ||||
-rw-r--r-- | disk-utils/sfdisk.8 | 9 | ||||
-rw-r--r-- | disk-utils/sfdisk.c | 10 | ||||
-rw-r--r-- | include/pt-mbr.h | 1 | ||||
-rw-r--r-- | lib/sysfs.c | 2 | ||||
-rw-r--r-- | libfdisk/docs/libfdisk-sections.txt | 6 | ||||
-rw-r--r-- | libfdisk/src/context.c | 33 | ||||
-rw-r--r-- | libfdisk/src/dos.c | 13 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 4 | ||||
-rw-r--r-- | libfdisk/src/gpt.c | 6 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h.in | 2 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.sym | 2 | ||||
-rw-r--r-- | libfdisk/src/partition.c | 3 | ||||
-rw-r--r-- | libfdisk/src/sgi.c | 2 | ||||
-rw-r--r-- | libfdisk/src/sun.c | 2 | ||||
-rw-r--r-- | libfdisk/src/utils.c | 73 | ||||
-rw-r--r-- | sys-utils/unshare.1 | 70 | ||||
-rw-r--r-- | sys-utils/unshare.c | 161 | ||||
-rw-r--r-- | tests/expected/sfdisk/dos-resize | 23 | ||||
-rw-r--r-- | tests/expected/sfdisk/gpt-resize | 23 | ||||
-rw-r--r-- | tests/functions.sh | 2 | ||||
-rwxr-xr-x | tests/ts/libmount/context | 50 | ||||
-rwxr-xr-x | tests/ts/libmount/context-py | 50 | ||||
-rwxr-xr-x | tests/ts/sfdisk/dos | 14 | ||||
-rwxr-xr-x | tests/ts/sfdisk/gpt | 15 |
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 |