bmaptool: distinguish between block devices and regular file
authorArtem Bityutskiy <artem.bityutskiy@intel.com>
Thu, 8 Nov 2012 15:26:04 +0000 (17:26 +0200)
committerArtem Bityutskiy <artem.bityutskiy@intel.com>
Thu, 8 Nov 2012 17:01:22 +0000 (19:01 +0200)
Teach bmaptool to distinguish between block devices and regular files and
use the specialized version of 'BmapCopy' in case of block devices. The
specialized version will be implemented in the 'BmapBdevCopy' class, which
is just a copy of the base class so far.

Change-Id: I444f121893dfd5d637a08300191c7a5dbc082d4e
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
bmaptool
bmaptools/BmapCopy.py

index 1745d38..96660e5 100755 (executable)
--- a/bmaptool
+++ b/bmaptool
@@ -37,6 +37,8 @@ VERSION = "0.1.1"
 
 import argparse
 import sys
+import os
+import stat
 import time
 import logging
 from bmaptools import BmapCreate, BmapCopy, BmapHelpers
@@ -44,8 +46,34 @@ from bmaptools import BmapCreate, BmapCopy, BmapHelpers
 def copy_command(args, log):
     """ Copy an image to a block device or a regular file using bmap. """
 
+    # Try to open the destination file. If it does not exist, a new regular
+    # file will be created. If it exists and it is a regular file - it'll be
+    # truncated. If this is a block device, it'll just be opened.
     try:
-        writer = BmapCopy.BmapCopy(args.image, args.dest, args.bmap)
+        dest_file = open(args.dest, 'w+')
+    except IOError as err:
+        log.error("cannot open destination file '%s': %s" \
+                  % (args.dest, err))
+        raise SystemExit(1)
+
+    dest_file.close()
+
+    # Check whether the destination file is a block device
+    try:
+        is_block_device = stat.S_ISBLK(os.stat(args.dest).st_mode)
+    except OSError as err:
+        log.error("cannot access destination file '%s': %s" \
+                   % (args.bdev, err.strerror))
+        raise SystemExit(1)
+
+    try:
+        if is_block_device:
+            # For block devices, use the specialized class
+            destination_type = "block device"
+            writer = BmapCopy.BmapBdevCopy(args.image, args.dest, args.bmap)
+        else:
+            destination_type = "file"
+            writer = BmapCopy.BmapCopy(args.image, args.dest, args.bmap)
     except BmapCopy.Error as err:
         log.error(str(err))
         raise SystemExit(1)
@@ -61,8 +89,8 @@ def copy_command(args, log):
                     writer.bmap_image_size_human, writer.bmap_mapped_cnt,
                     writer.bmap_mapped_size_human,
                     writer.bmap_mapped_percent))
-        log.info("copying the image to '%s' using bmap file '%s'" \
-                 % (args.dest, args.bmap))
+        log.info("copying the image to %s '%s' using bmap file '%s'" \
+                 % (destination_type, args.dest, args.bmap))
 
     try:
         try:
index ebf2766..07d1579 100644 (file)
@@ -469,3 +469,11 @@ class BmapCopy:
         except OSError as err:
             raise Error("cannot synchronize block device '%s': %s " \
                         % (self._bdev_path, err.strerror))
+
+class BmapBdevCopy(BmapCopy):
+    """ This class is a specialized version of 'BmapCopy' which copies the
+    image to a block device. Unlike the base 'BmapCopy' class, this class does
+    various optimizations specific to block devices, e.g., switchint to the
+    'noop' I/O scheduler. """
+
+    pass