]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: add --lock and LOCK_BLOCK_DEVICE
authorKarel Zak <kzak@redhat.com>
Wed, 27 May 2020 14:58:08 +0000 (16:58 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 27 May 2020 15:00:41 +0000 (17:00 +0200)
Addresses: https://github.com/karelzak/util-linux/issues/921
Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/fdisk.8
disk-utils/fdisk.c

index bb6e0588b6b6f8ad5ec7a49576b965223ce6eb99..e84782c461c75204211210dac6643bd2bd2e4427 100644 (file)
@@ -86,6 +86,14 @@ If no devices are given, those mentioned in
 \fB\-x\fR, \fB\-\-list\-details\fR
 Like \fB\-\-list\fR, but provides more details.
 .TP
+\fB\-\-lock\fR[=\fImode\fR]
+Use exclusive BSD lock for device or file it operates.  The optional argument
+\fImode\fP can be \fByes\fR, \fBno\fR (or 1 and 0) or \fBnonblock\fR.  If the \fImode\fR
+argument is omitted, it defaults to \fB"yes"\fR.  This option overwrites
+environment variable \fB$LOCK_BLOCK_DEVICE\fR.  The default is not to use any
+lock at all, but it's recommended to avoid collisions with udevd or other
+tools.
+.TP
 \fB\-n\fR, \fB\-\-noauto\-pt\fR
 Don't automatically create a default partition table on empty device.  The partition table
 has to be explicitly created by user (by command like 'o', 'g', etc.).
@@ -357,6 +365,8 @@ enables libblkid debug output.
 enables libsmartcols debug output.
 .IP LIBSMARTCOLS_DEBUG_PADDING=on
 use visible padding characters. Requires enabled LIBSMARTCOLS_DEBUG.
+.IP LOCK_BLOCK_DEVICE=<mode>
+use exclusive BSD lock.  The mode is "1" or "0".  See \fB\-\-lock\fR for more details.
 
 .SH AUTHORS
 .MT kzak@redhat.com
index bf5307b62f8e6443d8752160c47916bf3d494d51..f802d44c460112651cffc5b6325d871557111009 100644 (file)
@@ -873,6 +873,8 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -u, --units[=<unit>]          display units: 'cylinders' or 'sectors' (default)\n"), out);
        fputs(_(" -s, --getsz                   display device size in 512-byte sectors [DEPRECATED]\n"), out);
        fputs(_("     --bytes                   print SIZE in bytes rather than in human readable format\n"), out);
+       fprintf(out,
+             _("     --lock[=<mode>]           use exclusive device lock (%s, %s or %s)\n"), "yes", "no", "nonblock");
        fprintf(out,
              _(" -w, --wipe <mode>             wipe signatures (%s, %s or %s)\n"), "auto", "always", "never");
        fprintf(out,
@@ -906,8 +908,10 @@ int main(int argc, char **argv)
        int colormode = UL_COLORMODE_UNDEF;
        struct fdisk_context *cxt;
        char *outarg = NULL;
+       const char *devname, *lockmode = NULL;
        enum {
-               OPT_BYTES       = CHAR_MAX + 1
+               OPT_BYTES       = CHAR_MAX + 1,
+               OPT_LOCK
        };
        static const struct option longopts[] = {
                { "bytes",          no_argument,       NULL, OPT_BYTES },
@@ -920,6 +924,7 @@ int main(int argc, char **argv)
                { "help",           no_argument,       NULL, 'h' },
                { "list",           no_argument,       NULL, 'l' },
                { "list-details",   no_argument,       NULL, 'x' },
+               { "lock",           optional_argument, NULL, OPT_LOCK },
                { "noauto-pt",      no_argument,       NULL, 'n' },
                { "sector-size",    required_argument, NULL, 'b' },
                { "type",           required_argument, NULL, 't' },
@@ -1056,6 +1061,14 @@ int main(int argc, char **argv)
                case OPT_BYTES:
                        fdisk_set_size_unit(cxt, FDISK_SIZEUNIT_BYTES);
                        break;
+               case OPT_LOCK:
+                       lockmode = "1";
+                       if (optarg) {
+                               if (*optarg == '=')
+                                       optarg++;
+                               lockmode = optarg;
+                       }
+                       break;
                default:
                        errtryhelp(EXIT_FAILURE);
                }
@@ -1119,17 +1132,25 @@ int main(int argc, char **argv)
                fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n"
                                  "Be careful before using the write command.\n"));
 
-               rc = fdisk_assign_device(cxt, argv[optind], 0);
+               devname = argv[optind];
+               rc = fdisk_assign_device(cxt, devname, 0);
                if (rc == -EACCES) {
-                       rc = fdisk_assign_device(cxt, argv[optind], 1);
+                       rc = fdisk_assign_device(cxt, devname, 1);
                        if (rc == 0)
                                fdisk_warnx(cxt, _("Device is open in read-only mode."));
                }
                if (rc)
-                       err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
+                       err(EXIT_FAILURE, _("cannot open %s"), devname);
 
                fflush(stdout);
 
+               if (!fdisk_is_readonly(cxt)
+                   && blkdev_lock(fdisk_get_devfd(cxt), devname, lockmode) != 0) {
+                       fdisk_deassign_device(cxt, 1);
+                       fdisk_unref_context(cxt);
+                       return EXIT_FAILURE;
+               }
+
                if (fdisk_get_collision(cxt))
                        follow_wipe_mode(cxt);