Package gavo :: Package helpers :: Module copying
[frames] | no frames]

Source Code for Module gavo.helpers.copying

  1  """ 
  2  Helpers for pulling data from CDs, DVDs and similar media. 
  3  """ 
  4   
  5  #c Copyright 2008-2019, the GAVO project 
  6  #c 
  7  #c This program is free software, covered by the GNU GPL.  See the 
  8  #c COPYING file in the source distribution. 
  9   
 10   
 11  from __future__ import print_function 
 12   
 13  import fcntl 
 14  import os 
 15  import shutil 
 16  import subprocess 
 17  import sys 
 18  import time 
 19   
 20  from gavo import base 
 21  from gavo.user import ui  #noflake: Need side effect 
 22   
 23  CTL_CD_EJECT = 0x5309 
 24  CTL_CD_QCHANGE = 0x5325 
 25   
 26   
27 -class CDHandler(object):
28 """A wrapper for mounting and ejecting CDs. 29 30 This assumes that you let users mount CDs, e.g. via a line like 31 32 /dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0 33 34 in /etc/fstab. In this example, devPath would be /dev/scd0 and 35 mountPath /media/cdrom0. 36 """
37 - def __init__(self, devPath, mountPath):
38 self.devPath, self.mountPath = devPath, mountPath
39
40 - def ejectMedium(self):
41 """ejects the current CD. 42 """ 43 cd = os.open(self.devPath, os.O_RDONLY|os.O_NONBLOCK) 44 try: 45 fcntl.ioctl(cd, CTL_CD_EJECT) 46 finally: 47 if cd>=0: 48 os.close(cd)
49
50 - def mediumChanged(self):
51 """returns True if there's a new medium available. 52 """ 53 cd = os.open(self.devPath, os.O_RDONLY|os.O_NONBLOCK) 54 try: 55 if cd<0: 56 return False 57 else: 58 return fcntl.ioctl(cd, CTL_CD_QCHANGE, 0)==0 59 finally: 60 if cd>=0: 61 os.close(cd)
62
63 - def mount(self):
64 subprocess.check_call(["mount", self.mountPath])
65
66 - def unmount(self):
67 subprocess.check_call(["umount", self.devPath])
68
69 - def isMounted(self):
70 f = open("/proc/mounts") 71 stuff = f.read() 72 f.close() 73 return self.mountPath in stuff
74 75
76 -def _getCurMax(destBase):
77 """returns the highest index of ??\d+-formed names in destBase. 78 """ 79 def brutalInt(val): 80 try: 81 return int(val) 82 except ValueError: 83 return 0
84 try: 85 return max([brutalInt(n[2:]) for n in os.listdir(destBase)]+[0]) 86 except IOError: 87 return 0 88 89
90 -def changeCD(cdHandler):
91 if cdHandler.isMounted(): 92 cdHandler.unmount() 93 cdHandler.ejectMedium() 94 sys.stdout.write("Waiting for Medium") 95 sys.stdout.flush() 96 while not cdHandler.mediumChanged(): 97 time.sleep(1) 98 sys.stdout.write(".") 99 sys.stdout.flush()
100 101
102 -def readCDs(destBase, cdHandler):
103 """runs a crude UI to read CDs in batch. 104 105 The idea is that you get a copy-in script by writing something like 106 107 import os 108 from gavo import api 109 110 rd = api.getRD("foo/bar") 111 cd = CDHandler("/dev/cdrom", "mnt/cd") 112 copying.readCDs(os.path.join(rd.resdir, "raw"), cd) 113 """ 114 if not os.path.exists(destBase): 115 os.mkdir(destBase) 116 srcCount = 0 117 else: 118 srcCount = _getCurMax(destBase)+1 119 120 while 1: 121 changeCD(cdHandler) 122 dest = os.path.join(destBase, "cd%03d"%srcCount) 123 print("Now writing to", dest) 124 try: 125 cdHandler.mount() 126 shutil.copytree(cdHandler.mountPath, dest) 127 except (subprocess.CalledProcessError, shutil.Error, KeyboardInterrupt): 128 base.ui.notifyError("Copying failed or interrupted." 129 " Removing destination %s. Try again.")%dest 130 if os.path.exists(dest): 131 shutil.rmtree(dest) 132 sys.exit(1) 133 srcCount += 1
134