1 """
2 Helpers for pulling data from CDs, DVDs and similar media.
3 """
4
5
6
7
8
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
22
23 CTL_CD_EJECT = 0x5309
24 CTL_CD_QCHANGE = 0x5325
25
26
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 """
38 self.devPath, self.mountPath = devPath, mountPath
39
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
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
64 subprocess.check_call(["mount", self.mountPath])
65
67 subprocess.check_call(["umount", self.devPath])
68
70 f = open("/proc/mounts")
71 stuff = f.read()
72 f.close()
73 return self.mountPath in stuff
74
75
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
100
101
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