Re: Looking for multi-DVD spanning archiver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jun 6, 2010 at 10:08 PM, Robert G. (Doc) Savage
<dsavage@xxxxxxxxxxx> wrote:
> I wrote to the maintainer (James) and received the following reply:

Great minds think alike. I did the same and got pretty much the same
response. I've forwarded him my updates but I'll attach it here one
more time.

Some things I've added/fixed:
- Fixed DVD +R capacity (had an extra *2 in it)
- Got subprocess.Popen working
- Added a very basic usage (--help) output.
- Switched from a more procedural approach to capturing the main
portion of the program in a def Main() call and if __name__ ==
'__main__': which should make it easier to wrap a gui around it.
- Starting from disc other than #1. I hit enter too early on a backup
and it exited and I didn't want to burn the first two discs over.
- Got basic command parsing implemented.

Some things I was going to work on:
- assignable disc volume name by command line argument.

Richard
#! /usr/bin/python

import os, sys, os.path, math, tempfile, dbus, readline, getopt
from subprocess import *

def main():
  # Parse arguments
  try:
    opts, args = getopt.getopt(sys.argv[1:], 'hts:', ['help', 'test', 'disc-skip='])
  except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

  disc_skip = 0
  for opt, value in opts:
    if opt in ('-s', '--disc-skip'):
      disc_skip = value
    elif opt in ('-t', '--test'):
      test = True
    elif opt in ('-h', '--help'):
      usage()
      sys.exit(0)
    else:
      print "\nBad option: %s" % opt
      usage()
      sys.exit(0)

  try:  
    while True:
      try:
        dir = raw_input('Which directory would you like to backup?\n')
        if os.path.isdir(dir):
          dir = os.path.abspath(dir) + '/' # Add trailing slash here instead of later.
          break
        else:
          print "You must enter a valid directory."
          continue
      except: raise


    input = raw_input("\nPlease put a blank DVD in your drive so I can attempt to autodetect the device name and press Enter\n")
    drives = discover()
      
    if len(drives) == 1:
      statement = '\nUsing %s (%s) as your dvd burner, if this is wrong enter a valid one or press Enter to continue\n' % (drives.keys()[0], drives[drives.keys()[0]][1])
        
    elif len(drives) > 1:
      statement ='\nFound these capable dvd burners %s, enter one\n' % " ".join(drives).keys()
    else:
      statement ='\nNo dvd burner(s) found.  You may attempt to manually enter a device name\n'
      
    drive_input=raw_input(statement)
      
    if drive_input == "" and len(drives) ==1:
      drive = drives.keys()[0]
    else:
      drive = drive_input
      
    total_size = 0
    disc_capacity = int(drives[drive][0])
      
    print "The disc capacity of the disc in %s (%s) is %s GB" % (drive, drives[drive][1], str(disc_capacity / 1073741824.0) )
        
    speed = raw_input("\nEnter the speed which your drive and media support and press Enter\n")
      

    file_list = []
      
    for path, dirs, files in os.walk(dir):
      for filename in files:
        file_list.append(os.path.join(path, filename))
        print os.path.join(path, filename)
      
      
    file_list.sort()
      
    for file in file_list:
      if not os.path.islink(file):
        size = os.path.getsize(file)
        total_size = total_size + size
    if size >= disc_capacity:
      print "%s is larger than the capacity of the disc.  I can not span large files across discs."
      sys.exit(1)
    
      
    num_discs = int( math.ceil (total_size / disc_capacity) )
      
      
    (discs) = build_list(file_list, disc_capacity)
      
    print "\nNumber of %s's required to burn: %s" % ("dvd", len(discs))
      
    file_count = 0
      
    for disc in discs:
      file_count = file_count + len(disc)
      
    print "\nSanity Check\n"
    print "Total files in directory", len(file_list)
    print "Total files in all discs: ", file_count
      
      
    disc_num = 1

    # Really ugly way of skipping to a disc.
    if disc_skip > 0:
      print "Skipping to disc", disc_skip
      for disc in range(disc_skip-1):
        del discs[0]
  
    for disc in discs:
      burn(disc,dir, drive, speed, disc_num, len(discs))
      disc_num = disc_num + 1
  
  
  except KeyboardInterrupt:
    print "\nUser Interrupted.\n"
    sys.exit(1)
  except: raise

def usage():
  print """
Usage: discspan.py [OPTIONS]

Options:
-h, --help              This help.
-s, --disc-skip=<num>   Skip to a particular disk to burn.
-t, --test              Run but don't actually burn to disc."""

def discover():

  # get a connection to the system bus
  
  drives = []
  discs = {
  'dvd_r' : 4.38 * 1024 * 1024 * 1024,
  'dvd_rw' : 4.38 * 1024 * 1024 * 1024,
  'dvd_plus_r' : 4.37 * 1024 * 1024 * 1024,
  'dvd_plus_rw' : 4.37 * 1024 * 1024 * 1024,
  'dvd_plus_r_dl':  4.37 * 2 * 1024 * 1024 * 1024,
  'dvd_plus_rw_dl':  4.37 * 2 * 1024 * 1024 * 1024,

#  bd_re      If someone can test this with these new formats,
#  hddvd_rw   let me know!  I need values for their capacity
#  bd_r
#  hddvd_r
  }
  
  bus = dbus.SystemBus ()

  hal_obj = bus.get_object ('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
  hal = dbus.Interface (hal_obj, 'org.freedesktop.Hal.Manager')
  
  udis = hal.FindDeviceByCapability ('volume')
  drives = {}
  for udi in udis:

    dev_obj = bus.get_object ('org.freedesktop.Hal', udi)
    dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
    parent_obj = bus.get_object ('org.freedesktop.Hal', dev.GetProperty("info.parent"))
    parent = dbus.Interface (parent_obj, 'org.freedesktop.Hal.Device')
    
    if parent.GetProperty ('storage.hotpluggable') or 'storage.cdrom' in parent.GetProperty('info.capabilities'):
        try:
          if dev.GetProperty('volume.disc.type') in discs.keys():
            device_name = dev.GetProperty ('block.device')
            capacity = discs[dev.GetProperty('volume.disc.type')]
            print capacity
            drive_name = parent.GetProperty('info.product')
            drives[device_name] = [capacity, drive_name]
            print "Found a %s in %s (%s)" % (dev.GetProperty('volume.disc.type'), device_name, drive_name  )
        except:
          continue
        else:
          continue
              
  return drives

def RunCmd(command):
    
    print "Running command : %s" % command
    app = Popen(command, bufsize=0, shell=True, close_fds=True, stdout=PIPE, stderr=STDOUT)
    output= []
    while app.poll() == None: # Had to change from -1 or it never branched.
        while 1:

          try:
            line = app.stdout.readline().rstrip("\n")
            sys.stdout.flush() # Not sure if this is necessary but doesn't seem to hurt.
          except:
            pass
            
          if not line: break
          output.append(line)
          print line
        
    if app.poll() > 0 :
     
         print "There was an error running %s." % command
         sys.exit(1)

    return output


def build_list(files, dvd_capacity):
 
  file_count = 1
  disc_size = 0
  disc_list = []
  disc_files = []
  outfiles = []
 
  for file in files:
    
    if not os.path.islink(file):    
      size = os.path.getsize(file)
      disc_size = disc_size + size
    else:
      size = 0
    
    if disc_size >= dvd_capacity:
      disc_list.append(disc_files)
      disc_size = 0
      disc_size = disc_size + size
      disc_files = []
      disc_files.append(file)

    else:
      disc_files.append(file)
      
  disc_list.append(disc_files)

  return (disc_list)
    

def burn(disc, dir, drive, speed, disc_num, total_disc):
  
  if disc_num ==1:
    msg = "\nReady to burn disc %s/%s.  Press Enter"  % (disc_num, total_disc )
  else:
    msg = "\nInsert Empty Disc %s/%s and Press Enter\n" % (disc_num, total_disc )

  input=raw_input(msg)
  
  list = ""
  for file in disc:
    file_on_disc = file.replace(dir, "")
    list = list + "%s=%s\n" % (file_on_disc, file)
  fd, temp_list = tempfile.mkstemp(suffix=".discspanlist")
  output = open(temp_list, 'w')
  output.write(list)
  output.close()
  burn_cmd = "growisofs -Z %s -speed=%s -use-the-force-luke=notray" \
              " -use-the-force-luke=tty  -gui" \
              " -V DiscSpanData -A DiscSpan -p Unknown -iso-level 3" \
              " -l -r -hide-rr-moved -J -joliet-long" \
              " -graft-points --path-list %s" %(drive, speed, temp_list)
  
  if test == True:

      burn_cmd.append(' -use-the-force-luke=dummy')


  RunCmd(burn_cmd)
  os.unlink(temp_list)
  RunCmd("eject")
  
if __name__ == "__main__":
  sys.exit(main())
-- 
users mailing list
users@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe or change subscription options:
https://admin.fedoraproject.org/mailman/listinfo/users
Guidelines: http://fedoraproject.org/wiki/Mailing_list_guidelines

[Index of Archives]     [Current Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]     [Fedora Docs]

  Powered by Linux