This module implements an application for bulk copying USB flash drives (storage devices). The application was developed to run on Linux and is probably not particularly portable to other platforms.

From a user's perspective the operation is simple:

insert a 'master' USB key when prompted - the contents of the key will be copied into a temporary directory on the hard drive, after which the key can be removed

insert blank keys into all available USB ports - the app will detect when each new key is inserted, start the copy process and alert the user on completion

repeat step 2 as required

The program can write to multiple keys in parallel. It can also use filtering on device parameters to only overwrite devices which match the vendor name and storage capacity specified - other devices will be ignored.

The specifics of reading the master key, preparing a blank key (formatting parameters etc) are implemented in short 'profile' scripts (a reader and a writer). You can supply your own profile scripts if your requirements differ from those provided.

MASTER-WAIT waiting for the user to insert the master key
MASTER-COPYING waiting for the master key 'reader' script to complete
MASTER-COPIED waiting for the user to remove the master key
COPYING waiting for the user to insert blank keys

If the script was run by a non-root user and sudo is available, this string will be populated with the pathname of either gksudo or sudo. When running the read/writer scripts the string will be prepended onto the commands.

The tasks of reading a master key and writing to a blank key are delegated to 'reader' and 'writer' scripts. A pair of reader/writer scripts is supplied but the application also supports using different scripts as dictated by a user selection. The supplied scripts assume file-by-file copying and format the blank keys with a VFAT filesystem. An alternate script might for example, use dd to write a complete filesystem image in a single operation.

A pair of scripts is referred to as a copying 'profile'. The user can select a profile via a command-line option or from a drop-down list when confirming the master key.

The supplied scripts are called:

copyfiles-reader.sh
copyfiles-writer.sh

A profile does not need to include a reader script. If a profile which only includes a writer script is selected (via the command-line options) then the application will go immediately into the mode of waiting for blank keys.

The writer script will be passed the same set of variables and one extra:

USB_VOLUME_NAME e.g.: FREE-STUFF

Be warned that this variable may be empty - depending on what was returned from running dosfslabel against the master key. It is entirely reasonable for a custom writer script to ignore this variable altogether and either use a hardcoded volume label or not use one at all.

The writer script can also indicate progress (for updating the progress bar in the icon) by writing lines to STDOUT in the following format:

{x/y}

Where '{' is the first character on a line; 'x' is an integer indicating the number of steps completed; and 'y' is an integer indicating the total number of steps. For example if the script output this line:

The new method is used to create an application object. It in turn calls BUILD to create and populate the application window and hook into HAL (the Hardware Abstraction Layer) via DBus to get notifications of devices been added/removed.

Called from hal_device_added if the newly added device matches the current device filter settings. The key_info parameter supplied is a hashref of device properties as returned by hal_device_properties. A GUI widget representing the new USB key is added to the user interface and a data structure to track the copying process is created.

Called from the run method immediately before the application exits. This method is responsible for removing the temporary directories containing the master copy of the files and the mount points for the blank keys.

When running as a non-root user, this method needs to use sudo in order to remove the files created by the reader script when it was running as root.

This method is called each time a USB key is inserted when the application is in the MASTER-WAIT state. The key_info parameter supplied is a hashref of device properties as returned by hal_device_properties. this method displays a dialog box to allow the user to confirm that the device should be used as the master key.

If the user selects 'Cancel', no further action is taken and the application goes back to waiting for a master key to be inserted.

If the user confirms the device should be used as the master, then control is passed to the start_master_read method.

This method is called at startup to query GConf for the current GNOME/Nautilus media automount status ('true'/'false' for enabled/disabled). The current state is saved and then the value is set to false. The operation should fail silently in non-GNOME environments.

Called to handle a 'DeviceAdded' event from HAL via DBus. Delegates to start_master_read if the app is waiting for a master key. Otherwise checks whether the new device parameters match the current filter settings and delegates to add_key_to_rack if they do.

Called from hal_device_added to query HAL. Returns a hash(ref) of device details. The global variable %hal_device_added defines which attributes returned from HAL will appear in the hash and which keys they will be mapped to.

This method is called after the master key has been read (or immediately on startup if the selected profile does not use a reader script) and puts the application into the mode of waiting for blank keys to be inserted.

This method is used to select which reader/writer scripts will be used. At present there is one hard-coded call to this method in the constructor. Ideally, the user would select from all available profile scripts in the 'confirm master' dialog.

If the script is run by a non-root user and sudo is available and the --no-root-check option was not specified, this method will return a command string which wraps the supplied command in a call to either gksudo or sudo. For all other cases, command is returned unmodified.

The gksudo command is preferred since it gives the user a GUI prompt window if it is necessary to prompt for a password. This method handles the different semantics required to pass environment variables through gksudo and sudo.

Called from on_copier_pipe_read to update the status icon for a specified USB key device. The progress parameter is a number in the range 0-10 for copies in progress; -1 for a copy that has failed (non-zero exit status from the 'writer' process); or -2 to indicate a device which did not match the filter settings and is being ignored.