#! /usr/bin/python #+ # NAME: # burndisk # PURPOSE: # Burn CD or DVD from directory tree # CALLING SEQUENCE: # burndisk.py [-tar] directory # INPUTS: # directory top of directory tree to be burned on CD # OPTIONAL INPUTS: # -tar create zipped tar file and burn CD/DVD # -dvd needed to burn DVDs # -img only creates the CD image (no burning) # (in this case -nosudo and -dvd are ignored) # -nosudo launch cdrecord without using sudo # By default cdrecord is called using sudo. # This requires that /etc/sudoers is set up # correctly (see RESTRICTIONS). # If -nosudo is set then cdrecord is called directly. # This requires special user privileges. Never seem # to get it to work right. # -verbose produces more informational messages # -temp=temp directory where the CD image file and # tar file are created (default: $TUB) # -count=count indicates number of copies to be burned # (default:1) # -speed=speed write speed; default: none # -mode=mode burn mode; default: sao. # See REMARKS. # -dev=dev scsi dev for writer. Default: none # -email=email comma-separated list of email addresses to which # to send an email upon completion. # -exe=exe name of executable to use for burning disk # -nojoliet omits -J on mkisofs # -links adds -f to mkisofs (follows soft links) # # Some of keywords can be stored in env vars (a command line keyword always # takes precedence though): # # If make_dvd SET (burning DVDs): # keyword -mode: DVDMODE write mode # keyword -speed DVDSPEED write speed # If make_dvd NOT set (burning CDs) # keyword -mode: CDMODE write mode # keyword -dev: CDSPEED write speed # # RESTRICTIONS: # Burning the CD requires the program mkisofs to create the ISO file. # The CD/DVD is burned using cdrecord, or wodim (should be available # since Fedore Core 7). # # REMARKS: # I think, sao (session at once) is the same as dao (disk at once). # This is the default for cdrecord on most (but not all) of our Linux boxes. # Some versions use tao (track at once) by default. # One version of cdrecord we use does not accept mode sao at all, but when # called with dao said it was running in sao mode. Go figure. # # # RESTRICTIONS: # By default sudo is used to execute cdrecord. This requires that # /etc/sudoers needs to be set up correctly. Add a line like: # username ALL=(ALL) NOPASSWD: /cdrecord,/cdrecord-ProDVD # (remember to 'chmod u-w /etc/sudoers' after modifying the file or sudo # will refuse to access it). # # PROCEDURE: # The CD image and the tarball (if -tar is set) are created # in 'tempdir', and are deleted after processing. # # If called from another Python module: # status = burndisk(alldirs, burn_args) # then 'alldirs' is a list of directories, and burn_args is a # dictionary, set up with: # burn_args = dict \ # ( [ \ # ( 'make_tar', is_there( '-tar' , sys.argv ) ), \ # ( 'make_dvd', is_there( '-dvd' , sys.argv ) ), \ # ( 'make_img', is_there( '-img' , sys.argv ) ), \ # ( 'nosudo' , is_there( '-nosudo', sys.argv ) ), \ # ( 'verbose' , is_there( '-verbose',sys.argv ) ), \ # ( 'tempdir' , start ( '-temp=' , sys.argv ) ), \ # ( 'count' , start ( '-count=', sys.argv ) ), \ # ( 'speed' , start ( '-speed=', sys.argv ) ), \ # ( 'dev' , start ( '-dev=' , sys.argv ) ), \ # ( 'email' , start ( '-email=', sys.argv ) ), \ # ( 'exe' , start ( '-exe=' , sys.argv ) ), \ # ( 'nojoliet', is_there( '-nojoliet',sys.argv) ), \ # ( 'links' , is_there( '-links=', sys.argv ) ) ] ) # MODIFICATION HISTORY: # MAR-2003, Paul Hick (UCSD/CASS) # JUL-2003, Paul Hick (UCSD/CASS) # Modified to allow for multiple directories on cmd line. # OCT-2003, Paul Hick (UCSD/CASS) # Fixed bug with -tar keyword # JAN-2004, Paul Hick (UCSD/CASS) # Merged Austin Duncans burn_a_dvd.py with burn_a_cd.py and # renamed it burndisk.py. To burn DVDs set keyword -dvd # FEB-2004, Paul Hick (UCSD/CASS) # Modified to make callable from other Python modules # Added -temp keyword to set directory where tar ball and # CD image are created. # Added -count keyword to set # copies to be burned # MAR-2004, Paul Hick (UCSD/CASS) # Added -speed, -verbose and -dev keywords. # Changed to dictionary for list of args # Added a return value to burndisk. Status=0 is supposed # to indicate a succesful creation of a CD/DVD. ... Right. # For multiple directories the -graft-points option on mkisofs is # now used. The name of the subdirectory is used as the graft point. # JUL-2004, Paul Hick (UCSD/CASS) # Added check for env vars CDSPEED, CDWR, CDMODE (-dvd not set) # or DVDSPEED, DVDWR, DVDMODE (-dvd set) after checking for command # line arguments. # AUG-2004, Paul Hick (UCSD/CASS) # Replaced -sudo by -nosudo. Set default mode to sao. # Modified selection of program to burn CD/DVD. # AUG-2004, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Added -exe, -nojoliet and -links keyword # OCT-2005, Paul Hick (UCSD/CASS) # Modified selection of CD/DVD burning program. The default now # is cdrecord (which comes with the Linux distribution, usually # in /usr/bin). If this is not found then cdrecord-ProDVD is used, # if available. Remember that for burning DVDs this last program # requires cdrecord-wrapper.sh and a valid license key. # NOV-2005, Paul Hick (UCSD/CASS) # Added -dev=auto option to detect device name of CD/DVD device. # Currently this will select the first device returned by # cdrecord -scanbus (so it may not have the desired effect if # more than one CD/DVD device is present). # DEC-2007, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Removed references to cdrecord-ProDVD. Now the scripts first # looks for wodim (available since FC7) or cdrecord. # Env vars CDWR and DVDWR are not use anymore. To add the 'dev' # switch the -dev keyword must now be explicitly set. #- import os,sys from tiny import start, is_there, dict_entry, run_cmd, tomb, hide_env, args def burndisk(alldirs, burn_args): say = 'burndisk, ' tempdir = dict_entry( burn_args, 'tempdir' , os.environ['TUB'] ) make_tar = dict_entry( burn_args, 'make_tar', 0 ) make_dvd = dict_entry( burn_args, 'make_dvd', 0 ) make_img = dict_entry( burn_args, 'make_img', 0 ) nosudo = dict_entry( burn_args, 'nosudo' , 0 ) verbose = dict_entry( burn_args, 'verbose' , 0 ) links = dict_entry( burn_args, 'links' , 0 ) nojoliet = dict_entry( burn_args, 'nojoliet', 0 ) speed = dict_entry( burn_args, 'speed', '' ) dev = dict_entry( burn_args, 'dev' , '' ) mode = dict_entry( burn_args, 'mode' , '' ) email = dict_entry( burn_args, 'email', '' ) exe = dict_entry( burn_args, 'exe' , '' ) count = dict_entry( burn_args, 'count','1' ) count = int( count ) disk = (['CD','DVD'])[make_dvd] if dev == 'auto': burncmd = run_cmd( 'which wodim 2> /dev/null', 0 ) if burncmd == '': burncmd = run_cmd( 'which cdrecord 2> /dev/null', 0 ) if burncmd == '': status = 1 print say+'unable to find wodim or cdrecord' return status burncmd = (burncmd.split( '\n' ))[0] dev = '' for tmp in (run_cmd(burncmd+' -scanbus 2> /dev/null', 0)).split('\n'): if tmp[0:1] == '\t': blank,dev,name = tmp.split('\t') if name.find('*') == -1: break if dev == '': status = 1 print say+'unable to determine '+disk+' writer' return status print say+'with '+dev+' = '+name if speed == '': speed = dict_entry( os.environ, disk+'SPEED', '' ) if mode == '': mode = dict_entry( os.environ, disk+'MODE' , 'sao' ) if mode != '': mode = '-'+mode graft = '' is_image = 0 if make_tar: top_dir = ' '.join( alldirs ) # Create a tarball archive = os.path.join(tempdir,'burndisk.tar.gz') run_cmd( 'tar -czvf '+archive+' '+top_dir, verbose ) size = '%d'%(os.stat(archive)).st_size print archive, size, 'bytes (', tomb( size ), 'MB)\n' elif len( alldirs ) == 1: # If a single file is specified, assume it is a CD/DVD image archive = alldirs[0] is_image = os.path.isfile( archive ) else: graft = '-graft-points' archive = '' for subdir in alldirs: if subdir[len(subdir)-1] == '/': tmp = subdir[0:len(subdir)-1] else: tmp = subdir archive += ' '+(os.path.split(tmp))[1]+'/='+tmp archive = archive[1:len(archive)] if is_image: make_img = 0 cd_img = archive else: # Create the CD image from the tar archive (make_tar = 1) # or from the top directory (make_tar = 0). cd_img = os.path.join(tempdir,'burndisk.img') print say+'mkisofs ...' options = ' -R' if not nojoliet: options += 'J' if links: options += ' -f' run_cmd( 'mkisofs '+graft+options+' -quiet -o '+cd_img+' '+archive, verbose ) if make_tar: os.remove( archive ) # Are we burning a CD or a DVD if not os.path.exists(cd_img): # There should be a disk image file available status = 1 message = disk+' image does not exist: '+hide_env(cd_img) elif make_img: # Disk image has been made. Skip burning of CD/DVD status = 0 message = disk+' image is '+hide_env(cd_img) else: # Burn CD/DVD cd_size = '%d'%(os.stat(cd_img)).st_size status = 0 if exe == '': # Keyword -exe NOT set. Select burn executable here. # The first choice is wodim. The second is cdrecord. burncmd = run_cmd( 'which wodim 2> /dev/null', 0 ) if burncmd == '': burncmd = run_cmd( 'which cdrecord 2> /dev/null', 0 ) if burncmd == '': message = 'unable to find wodim or cdrecord' status = 1 else: # Keyword -exe SET. Find the executable print say+exe+' ...' burncmd = run_cmd( 'which '+exe, 0 ) if burncmd == '': message = 'unable to find '+exe status = 1 burncmd = (burncmd.split( '\n' ))[0] # Write the CD, then remove the CD image file if status == 0: cmd = (['sudo',burncmd])[nosudo] args = [] if not nosudo: args.append( 'sudo' ) args.extend( [burncmd, '-eject', '-data'] ) if dev != '': args.append( 'dev=' +dev ) if speed != '': args.append( 'speed='+speed ) if mode != '': args.append( mode ) args.append( cd_img ) # If run_cmd can be made to return a proper error code it would # probably be a better way to execute cdrecord #run_cmd( burncmd, verbose ) status = os.spawnvp(os.P_WAIT, cmd, args) if status == 0: message = disk+' burn finished OK' for n in range(count-1): print say+message try_again = 1 while try_again: dummy = raw_input('insert blank '+disk+' for disk %d and hit any key'%(n+2)) status = os.spawnvp(os.P_WAIT, cmd, args) if status == 0: try_again = 0 message = disk+' burn of disk %d finished OK'%(n+2) else: print say+'something wrong? Return status: %d'%status try_again = raw_input('try disk %d again (yes/no) ? [no]'%(n+2)) try_again = (try_again.lower())[0] == 'y' if not try_again: message = 'disk %d discontinued'%(n+2) else: message = 'something wrong? Return status: %d'%status if status == 0: if not is_image: os.remove( cd_img ) print '\n'+cd_img, cd_size, 'bytes (', tomb( cd_size ), 'MB)\n' print say+message if email != "": run_cmd( 'echo "'+message+'" | mail '+email+' -s"'+message+'"', 0 ) return status if __name__ == '__main__': import sys alldirs = args(sys.argv) if len(alldirs) == 1: print "Syntax: burndisk [-dvd] >" sys.exit() # Check for keywords burn_args = dict \ ( [ \ ( 'make_tar', is_there( '-tar' , sys.argv ) ), \ ( 'make_dvd', is_there( '-dvd' , sys.argv ) ), \ ( 'make_img', is_there( '-img' , sys.argv ) ), \ ( 'nosudo' , is_there( '-nosudo', sys.argv ) ), \ ( 'verbose' , is_there( '-verbose',sys.argv ) ), \ ( 'tempdir' , start ( '-temp=' , sys.argv ) ), \ ( 'count' , start ( '-count=', sys.argv ) ), \ ( 'speed' , start ( '-speed=', sys.argv ) ), \ ( 'dev' , start ( '-dev=' , sys.argv ) ), \ ( 'mode' , start ( '-mode=' , sys.argv ) ), \ ( 'email' , start ( '-email=', sys.argv ) ), \ ( 'exe' , start ( '-exe=' , sys.argv ) ), \ ( 'nojoliet', is_there( '-nojoliet',sys.argv) ), \ ( 'links' , is_there( '-links' , sys.argv ) ) ] ) # List of directories to be put on CD. # Drop alldirs[0] (name of this script) alldirs = alldirs[1:len(alldirs)] burndisk( alldirs, burn_args ) sys.exit()