Commits

wodny  committed 9e43772 Merge

Merge full-drive-writer

  • Participants
  • Parent commits 3d9ebf8, 0bd4104

Comments (0)

Files changed (10)

File lib/config.py

     def __init__(self, path):
         self.path = path
 
-        self.parser = ConfigParser.SafeConfigParser()
+        self.parser = ConfigParser.SafeConfigParser(
+            {"dest_prefix": ""}
+        )
         self.parser.read(path)
 
         # Validation
 
         self.postscript = self.prefix_with_basedir(self.postscript)
 
-        if self.mode not in ("copy-only", "create-mbr"):
+        if self.mode not in ("copy-only", "create-mbr", "full-drive-image"):
             raise ConfigException("Invalid mode")
 
-        self.partitions = [
-            int(part)
-            for part
-            in self.parser.get("general", "partitions").split(',')
-        ]
+        partition_list = self.parser.get("general", "partitions")
+        if partition_list != "":
+            self.partitions = [
+                int(part)
+                for part
+                in partition_list.split(',')
+            ]
+        else:
+            self.partitions = []
+            self.fulldriveimage = self.get_partdata_spec(0)[0]
         self.partitions.sort()
-
         self.partspecs = dict()
-
         for p in self.partitions:
             section = "partition_{0}".format(p)
             self.partspecs[p] = dict()
             self.partspecs[p]["postscript"] = self.prefix_with_basedir(
                 self.parser.get(section, "postscript")
             )
+            self.partspecs[p]["dest_prefix"] = self.parser.get(
+                section,
+                "dest_prefix"
+            )
 
     def prefix_with_basedir(self, path):
         if not path:

File lib/datawriter.py

 
 
 import subprocess
+import os.path
 
 from drive_statuses import DriveStatus
 from partition_statuses import PartitionStatus
 from datawriter_events import StatusUpdate
 from dbus_tools import DBusTools
-from dbus_virtevents import MBRCreated, PartitionsCreated, FSCreated
+from dbus_virtevents import MBRCreated, PartitionsCreated, FullDriveDone, FSCreated
 
 import dbus
 import logging
 
         return PartitionsCreated(self.drive)
 
+class FullDriveWriter:
+    def __init__(self, events_in, request):
+        self.events_in = events_in
+        self.request = request
+
+        self.drive = request.drive
+        self.tools = DBusTools()
+
+    def run(self):
+        logging.info(_("FullDriveWriter starting {0}...").format(self.drive))
+        self.events_in.put(
+            StatusUpdate(
+                self.drive,
+                None,
+                None,
+                None,
+                _("About to write an image on {0}...").format(self.drive)
+            )
+        )
+
+        try:
+            cmd = [
+                "dd",
+                "bs=8M",
+                "conv=fsync",
+                "if={0}".format(self.request.config.fulldriveimage),
+                "of={0}".format(self.tools.get_device_filename(self.drive))
+            ]
+            logging.debug(_("Executing copy command {0}...").format(cmd))
+            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+            for line in output.split('\n'):
+                logging.debug(_("Command output: {0}").format(line))
+        except subprocess.CalledProcessError as e:
+            for line in e.output.split('\n'):
+                logging.error(_("Command output: {0}").format(line))
+            logging.error(_("Error executing copy command: {0}").format(e))
+            self.events_in.put(
+                StatusUpdate(
+                    self.drive,
+                    DriveStatus.DRIVE_ERROR_DRV,
+                    None,
+                    None,
+                    _("Error while writing image to {0}!").format(self.drive)
+                )
+            )
+            return
+
+        return FullDriveDone(self.drive)
+
 
 class PartitionWriter:
     def __init__(self, events_in, request):
                     "--delete",
                     "--",
                     self.partspec["path"],
-                    mountpoint
+                    os.path.join(mountpoint, self.partspec["dest_prefix"])
                 ]
             if self.partspec["method"] == "copy-image":
                 cmd = [

File lib/datawriter_launcher.py

         writer_event = w.run()
         self.postrun(writer_event, DataWriterDone(self.request.drive))
 
+class FullDriveWriterLauncher(DataWriterLauncher):
+    def __init__(self, events_in, request):
+        DataWriterLauncher.__init__(self, events_in, request)
+
+    def run(self):
+        self.prerun()
+        from datawriter import FullDriveWriter
+        w = FullDriveWriter(self.events_in, self.request)
+        writer_event = w.run()
+        self.postrun(writer_event, DataWriterDone(self.request.drive))
 
 class PartitionWriterLauncher(DataWriterLauncher):
     def __init__(self, events_in, request):

File lib/datawriter_requests.py

 #    along with pendrive-frenzy.  If not, see <http://www.gnu.org/licenses/>.
 
 
-from datawriter_launcher import MBRWriterLauncher, PartitionWriterLauncher
+from datawriter_launcher import MBRWriterLauncher, FullDriveWriterLauncher, PartitionWriterLauncher
 import logging
 
 
         l = MBRWriterLauncher(events_in, self)
         writers[self.drive] = l
         l.start()
+
+class FullDriveWriterRequest(DataWriterRequest):
+    def __init__(self, drive, config):
+        self.drive = drive
+        self.config = config
+        self.partspecs = config.partspecs
+
+    def handle(self, writers, events_in):
+        logging.debug(_("Requested FullDriveWriter for {0}.").format(self.drive))
+        if self.drive in writers:
+            logging.error(
+                _("Already have FullDriveWriter for {0}!").format(
+                    self.drive
+                )
+            )
+            return
+        logging.debug(_("Spawning FullDriveWater for {0}...").format(self.drive))
+        l = FullDriveWriterLauncher(events_in, self)
+        writers[self.drive] = l
+        l.start()

File lib/dbus_events.py

 import gui_updates
 from drive_statuses import DriveStatus
 from partition_statuses import PartitionStatus
-from datawriter_requests import PartitionWriterRequest, MBRWriterRequest
+from datawriter_requests import PartitionWriterRequest, MBRWriterRequest, FullDriveWriterRequest
 import tools
 
 
                         dispatch.config
                     )
                 )
-            else:
+            elif dispatch.config.mode == "full-drive-image":
+                dispatch.drive_statuses[self.drive] = \
+                    DriveStatus.DRIVE_INPROGRESS_DRV
+                dispatch.writers_in.put(
+                    FullDriveWriterRequest(
+                        self.drive,
+                        dispatch.config
+                    )
+                )
+            elif dispatch.config.mode == "copy-only":
                 dispatch.drive_statuses[self.drive] = DriveStatus.DRIVE_NEW
         dispatch.updates_in.put(gui_updates.DriveAdded(self.drive, self.port))
         dispatch.update_status(self.drive, "New drive {0}.".format(self.drive))
         self.part = part
 
     def handle(self, dispatch):
-        if dispatch.config and dispatch.config.mode == "create-mbr":
+        if dispatch.config and dispatch.config.mode in ("create-mbr", "full-drive-image"):
             return
 
         complete = dispatch.account_partition_added(

File lib/dbus_handler.py

         self.tools = DBusTools()
         self.tools.get_device("/org/freedesktop/UDisks")
 
+        self.drives = dict()
+
     def handler(self, *args, **kwargs):
         member = kwargs['member']
 
            self.tools.is_drive(path) and \
            self.tools.get_conn_interface(path) == "usb":
             driveid = self.tools.get_drive_id(path)
-            logging.info(_("New drive {0} {1}.").format(path, driveid))
             port = self.tools.get_port(path)
-            self.events_in.put(DriveAdded(path, port))
+            size = self.tools.get_device_size(path)
+            logging.info(_("New drive {0} {1} (size={2}).").format(path, driveid, size))
+            if size != 0:
+                self.events_in.put(DriveAdded(path, port))
+            self.drives[path] = size
+
+        if member == "DeviceChanged" and \
+           self.tools.is_drive(path) and \
+           self.tools.get_conn_interface(path) == "usb":
+            driveid = self.tools.get_drive_id(path)
+            port = self.tools.get_port(path)
+            size = self.tools.get_device_size(path)
+            logging.info(_("Drive {0} {1} changed (size={2}).").format(path, driveid, size))
+            if path in self.drives and self.drives[path] == 0 and size != 0:
+                self.events_in.put(DriveAdded(path, port))
+            if path in self.drives and size == 0:
+                self.events_in.put(DeviceRemoved(path))
+            self.drives[path] = size
+
         if member == "DeviceAdded" and self.tools.is_partition(path):
             logging.debug(_("New partition {0}.").format(path))
             self.events_in.put(
             )
         if member == "DeviceRemoved":
             logging.debug(_("Removed device {0}.").format(path))
+            try:
+                del self.drives[path]
+            except KeyError:
+                pass
             self.events_in.put(DeviceRemoved(path))

File lib/dbus_virtevents.py

             _("Created partitions on {0}.").format(self.drive)
         )
 
+class FullDriveDone(DBusVirtEvent):
+    def __init__(self, drive):
+        self.drive = drive
+
+    def handle(self, dispatch):
+        logging.debug(_("Full drive image copy done for {0}.").format(self.drive))
+        dispatch.drive_statuses[self.drive] = DriveStatus.DRIVE_DONE_DRV
+        dispatch.update_status(
+            self.drive,
+            _("Full drive image copy done for {0}.").format(self.drive)
+        )
+
+
 
 class FSCreated(DBusVirtEvent):
     def __init__(self, drive, part):

File lib/dispatch.py

             drive_text = "Failed creating MBR."
         if drive_status == DriveStatus.DRIVE_WAITFORPT:
             drive_text = "Waiting for MBR..."
+        if drive_status == DriveStatus.DRIVE_INPROGRESS_DRV:
+            drive_text = "Writing image..."
+        if drive_status == DriveStatus.DRIVE_DONE_DRV:
+            drive_text = "Done."
+        if drive_status == DriveStatus.DRIVE_ERROR_DRV:
+            drive_text = "Error."
+
 
         if not (drive_status & DriveStatus.DRIVE_PT):
             failed_text = ""

File lib/drive_statuses.py

     DRIVE_DONE = 0x03
     DRIVE_PARTERROR = 0x84
 
+    DRIVE_INPROGRESS_DRV = 0x42
+    DRIVE_DONE_DRV = 0x43
+    DRIVE_ERROR_DRV = 0xC0
+
     DRIVE_WAITFORPT = 0x45
     DRIVE_PTERROR = 0xC7
 

File lib/pendrivestore.py

         DriveStatus.DRIVE_NEW: COLOR_NEW,
         DriveStatus.DRIVE_HASPT: COLOR_INPROGRESS,
         DriveStatus.DRIVE_INPROGRESS: COLOR_INPROGRESS,
+        DriveStatus.DRIVE_INPROGRESS_DRV: COLOR_INPROGRESS,
         DriveStatus.DRIVE_WAITFORPT: COLOR_INPROGRESS,
         DriveStatus.DRIVE_PTERROR: COLOR_INPROGRESS,
         DriveStatus.DRIVE_DONE: COLOR_DONE,
+        DriveStatus.DRIVE_DONE_DRV: COLOR_DONE,
     }
 
     COLUMN_STATUSTEXT = 2