home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_815 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  28.4 KB  |  1,006 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2009, John Schember <john at nachtimwald.com> 2009, Kovid Goyal <kovid@kovidgoyal.net>'
  6. __docformat__ = 'restructuredtext en'
  7. import os
  8. import subprocess
  9. import time
  10. import re
  11. import sys
  12. import glob
  13. import operator
  14. from itertools import repeat
  15. from calibre.devices.interface import DevicePlugin
  16. from calibre.devices.errors import DeviceError, FreeSpaceError
  17. from calibre.devices.usbms.deviceconfig import DeviceConfig
  18. from calibre.constants import iswindows, islinux, isosx, plugins
  19. from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
  20. if isosx:
  21.     (usbobserver, usbobserver_err) = plugins['usbobserver']
  22.  
  23.  
  24. class USBDevice:
  25.     
  26.     def __init__(self, dev):
  27.         self.idVendor = dev[0]
  28.         self.idProduct = dev[1]
  29.         self.bcdDevice = dev[2]
  30.         self.manufacturer = dev[3]
  31.         self.product = dev[4]
  32.         self.serial = dev[5]
  33.  
  34.     
  35.     def match_serial(self, serial):
  36.         if self.serial:
  37.             pass
  38.         return self.serial == serial
  39.  
  40.     
  41.     def match_numbers(self, vid, pid, bcd):
  42.         if self.idVendor == vid and self.idProduct == pid:
  43.             pass
  44.         return self.bcdDevice == bcd
  45.  
  46.     
  47.     def match_strings(self, vid, pid, bcd, man, prod):
  48.         if self.match_numbers(vid, pid, bcd) and self.manufacturer == man:
  49.             pass
  50.         return self.product == prod
  51.  
  52.  
  53.  
  54. class Device(DeviceConfig, DevicePlugin):
  55.     VENDOR_ID = 0
  56.     PRODUCT_ID = 0
  57.     BCD = None
  58.     VENDOR_NAME = None
  59.     WINDOWS_MAIN_MEM = None
  60.     WINDOWS_CARD_A_MEM = None
  61.     WINDOWS_CARD_B_MEM = None
  62.     OSX_MAIN_MEM = None
  63.     OSX_CARD_A_MEM = None
  64.     OSX_CARD_B_MEM = None
  65.     OSX_MAIN_MEM_VOL_PAT = None
  66.     OSX_EJECT_COMMAND = [
  67.         'diskutil',
  68.         'eject']
  69.     MAIN_MEMORY_VOLUME_LABEL = ''
  70.     STORAGE_CARD_VOLUME_LABEL = ''
  71.     STORAGE_CARD2_VOLUME_LABEL = None
  72.     EBOOK_DIR_MAIN = ''
  73.     EBOOK_DIR_CARD_A = ''
  74.     EBOOK_DIR_CARD_B = ''
  75.     DELETE_EXTS = []
  76.     
  77.     def reset(self, key = '-1', log_packets = False, report_progress = None, detected_device = None):
  78.         self._main_prefix = None
  79.         self._card_a_prefix = None
  80.         self._card_b_prefix = None
  81.         
  82.         try:
  83.             self.detected_device = USBDevice(detected_device)
  84.         except:
  85.             self.detected_device = None
  86.  
  87.         self.set_progress_reporter(report_progress)
  88.  
  89.     
  90.     def set_progress_reporter(self, report_progress):
  91.         self.report_progress = report_progress
  92.         self.report_progress = report_progress
  93.         if self.report_progress is None:
  94.             
  95.             self.report_progress = lambda x, y: x
  96.         
  97.  
  98.     
  99.     def card_prefix(self, end_session = True):
  100.         return (self._card_a_prefix, self._card_b_prefix)
  101.  
  102.     
  103.     def _windows_space(cls, prefix):
  104.         if not prefix:
  105.             return (0, 0)
  106.         prefix = prefix[:-1]
  107.         win32file = __import__('win32file', globals(), locals(), [], -1)
  108.         
  109.         try:
  110.             (sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters) = win32file.GetDiskFreeSpace(prefix)
  111.         except Exception:
  112.             prefix
  113.             err = prefix
  114.             if getattr(err, 'args', [
  115.                 None])[0] == 21:
  116.                 time.sleep(3)
  117.                 (sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters) = win32file.GetDiskFreeSpace(prefix)
  118.             else:
  119.                 raise 
  120.             getattr(err, 'args', [
  121.                 None])[0] == 21
  122.  
  123.         mult = sectors_per_cluster * bytes_per_sector
  124.         return (total_clusters * mult, free_clusters * mult)
  125.  
  126.     _windows_space = classmethod(_windows_space)
  127.     
  128.     def total_space(self, end_session = True):
  129.         msz = casz = cbsz = 0
  130.         if not iswindows:
  131.             if self._main_prefix is not None:
  132.                 stats = os.statvfs(self._main_prefix)
  133.                 msz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
  134.             
  135.             if self._card_a_prefix is not None:
  136.                 stats = os.statvfs(self._card_a_prefix)
  137.                 casz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
  138.             
  139.             if self._card_b_prefix is not None:
  140.                 stats = os.statvfs(self._card_b_prefix)
  141.                 cbsz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree)
  142.             
  143.         else:
  144.             msz = self._windows_space(self._main_prefix)[0]
  145.             casz = self._windows_space(self._card_a_prefix)[0]
  146.             cbsz = self._windows_space(self._card_b_prefix)[0]
  147.         return (msz, casz, cbsz)
  148.  
  149.     
  150.     def free_space(self, end_session = True):
  151.         msz = casz = cbsz = 0
  152.         if not iswindows:
  153.             if self._main_prefix is not None:
  154.                 stats = os.statvfs(self._main_prefix)
  155.                 msz = stats.f_frsize * stats.f_bavail
  156.             
  157.             if self._card_a_prefix is not None:
  158.                 stats = os.statvfs(self._card_a_prefix)
  159.                 casz = stats.f_frsize * stats.f_bavail
  160.             
  161.             if self._card_b_prefix is not None:
  162.                 stats = os.statvfs(self._card_b_prefix)
  163.                 cbsz = stats.f_frsize * stats.f_bavail
  164.             
  165.         else:
  166.             msz = self._windows_space(self._main_prefix)[1]
  167.             casz = self._windows_space(self._card_a_prefix)[1]
  168.             cbsz = self._windows_space(self._card_b_prefix)[1]
  169.         return (msz, casz, cbsz)
  170.  
  171.     
  172.     def windows_filter_pnp_id(self, pnp_id):
  173.         return False
  174.  
  175.     
  176.     def windows_match_device(self, pnp_id, attr):
  177.         device_id = getattr(self, attr)
  178.         
  179.         def test_vendor():
  180.             vendors = None if isinstance(self.VENDOR_NAME, basestring) else self.VENDOR_NAME
  181.             for v in vendors:
  182.                 if 'VEN_' + str(v).upper() in pnp_id:
  183.                     return True
  184.             
  185.             return False
  186.  
  187.         if device_id is None or not test_vendor():
  188.             return False
  189.         if self.windows_filter_pnp_id(pnp_id):
  190.             return False
  191.         if hasattr(device_id, 'search'):
  192.             return device_id.search(pnp_id) is not None
  193.         for x in device_id:
  194.             x = x.upper()
  195.             if 'PROD_' + x in pnp_id:
  196.                 return True
  197.         
  198.         return False
  199.  
  200.     
  201.     def windows_sort_drives(self, drives):
  202.         return drives
  203.  
  204.     
  205.     def can_handle_windows(self, device_id, debug = False):
  206.         win_pnp_drives = win_pnp_drives
  207.         import calibre.devices.scanner
  208.         drives = win_pnp_drives()
  209.         for pnp_id in drives.values():
  210.             if self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM'):
  211.                 return True
  212.             if debug:
  213.                 print '\tNo match found in:', pnp_id
  214.                 continue
  215.         
  216.         return False
  217.  
  218.     
  219.     def open_windows(self):
  220.         win_pnp_drives = win_pnp_drives
  221.         import calibre.devices.scanner
  222.         time.sleep(5)
  223.         drives = { }
  224.         for drive, pnp_id in win_pnp_drives().items():
  225.             if self.windows_match_device(pnp_id, 'WINDOWS_CARD_A_MEM') and not drives.get('carda', False):
  226.                 drives['carda'] = drive
  227.             elif self.windows_match_device(pnp_id, 'WINDOWS_CARD_B_MEM') and not drives.get('cardb', False):
  228.                 drives['cardb'] = drive
  229.             elif self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM') and not drives.get('main', False):
  230.                 drives['main'] = drive
  231.             
  232.             if 'main' in drives.keys() and 'carda' in drives.keys() and 'cardb' in drives.keys():
  233.                 break
  234.                 continue
  235.         
  236.         if drives.get('carda', None) is not None and drives.get('main', None) is None:
  237.             drives['main'] = drives.pop('carda')
  238.         
  239.         if drives.get('main', None) is None:
  240.             raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.') % self.__class__.__name__)
  241.         drives.get('main', None) is None
  242.         if self.WINDOWS_MAIN_MEM in (self.WINDOWS_CARD_A_MEM, self.WINDOWS_CARD_B_MEM) or self.WINDOWS_CARD_A_MEM == self.WINDOWS_CARD_B_MEM:
  243.             letters = sorted(drives.values(), key = operator.attrgetter('order'))
  244.             drives = { }
  245.             for which, letter in zip([
  246.                 'main',
  247.                 'carda',
  248.                 'cardb'], letters):
  249.                 drives[which] = letter
  250.             
  251.         
  252.         drives = self.windows_sort_drives(drives)
  253.         self._main_prefix = drives.get('main')
  254.         self._card_a_prefix = drives.get('carda', None)
  255.         self._card_b_prefix = drives.get('cardb', None)
  256.  
  257.     
  258.     def run_ioreg(cls, raw = None):
  259.         if raw is not None:
  260.             return raw
  261.         ioreg = '/usr/sbin/ioreg'
  262.         if not os.access(ioreg, os.X_OK):
  263.             ioreg = 'ioreg'
  264.         
  265.         cmd = (ioreg + ' -w 0 -S -c IOMedia').split()
  266.         for i in range(3):
  267.             
  268.             try:
  269.                 return subprocess.Popen(cmd, stdout = subprocess.PIPE).communicate()[0]
  270.             except IOError:
  271.                 if i == 2:
  272.                     raise 
  273.                 i == 2
  274.  
  275.             time.sleep(2)
  276.         
  277.  
  278.     run_ioreg = classmethod(run_ioreg)
  279.     
  280.     def osx_sort_names(self, names):
  281.         return names
  282.  
  283.     
  284.     def check_ioreg_line(self, line, pat):
  285.         if pat is None:
  286.             return False
  287.         if not line.strip().endswith('<class IOMedia>'):
  288.             return False
  289.         if hasattr(pat, 'search'):
  290.             return pat.search(line) is not None
  291.         for x in pat:
  292.             if x in line:
  293.                 return True
  294.         
  295.         return False
  296.  
  297.     
  298.     def get_osx_mountpoints(self, raw = None):
  299.         raw = self.run_ioreg(raw)
  300.         lines = raw.splitlines()
  301.         names = { }
  302.         
  303.         def get_dev_node(lines, loc):
  304.             for line in lines:
  305.                 line = line.strip()
  306.                 if line.endswith('}'):
  307.                     break
  308.                 
  309.                 match = re.search('"BSD Name"\\s+=\\s+"(.*?)"', line)
  310.                 if match is not None:
  311.                     names[loc] = match.group(1)
  312.                     break
  313.                     continue
  314.             
  315.  
  316.         for i, line in enumerate(lines):
  317.             if 'main' not in names and self.check_ioreg_line(line, self.OSX_MAIN_MEM):
  318.                 get_dev_node(lines[i + 1:], 'main')
  319.                 continue
  320.             
  321.             if 'carda' not in names and self.check_ioreg_line(line, self.OSX_CARD_A_MEM):
  322.                 get_dev_node(lines[i + 1:], 'carda')
  323.                 continue
  324.             
  325.             if 'cardb' not in names and self.check_ioreg_line(line, self.OSX_CARD_B_MEM):
  326.                 get_dev_node(lines[i + 1:], 'cardb')
  327.                 continue
  328.             
  329.             if len(names.keys()) == 3:
  330.                 break
  331.                 continue
  332.         
  333.         return self.osx_sort_names(names)
  334.  
  335.     
  336.     def osx_run_mount(cls):
  337.         for i in range(3):
  338.             
  339.             try:
  340.                 return subprocess.Popen('mount', stdout = subprocess.PIPE).communicate()[0]
  341.             except IOError:
  342.                 if i == 2:
  343.                     raise 
  344.                 i == 2
  345.  
  346.             time.sleep(2)
  347.         
  348.  
  349.     osx_run_mount = classmethod(osx_run_mount)
  350.     
  351.     def osx_get_usb_drives(cls):
  352.         if usbobserver_err:
  353.             raise RuntimeError('Failed to load usbobserver: ' + usbobserver_err)
  354.         usbobserver_err
  355.         return usbobserver.get_usb_drives()
  356.  
  357.     osx_get_usb_drives = classmethod(osx_get_usb_drives)
  358.     
  359.     def _osx_bsd_names(self):
  360.         drives = self.osx_get_usb_drives()
  361.         matches = []
  362.         d = self.detected_device
  363.         if d.serial:
  364.             for path, vid, pid, bcd, ven, prod, serial in drives:
  365.                 if d.match_serial(serial):
  366.                     matches.append(path)
  367.                     continue
  368.             
  369.         
  370.         if not matches:
  371.             if d.manufacturer and d.product:
  372.                 for path, vid, pid, bcd, man, prod, serial in drives:
  373.                     if d.match_strings(vid, pid, bcd, man, prod):
  374.                         matches.append(path)
  375.                         continue
  376.                 
  377.             else:
  378.                 for path, vid, pid, bcd, man, prod, serial in drives:
  379.                     if d.match_numbers(vid, pid, bcd):
  380.                         matches.append(path)
  381.                         continue
  382.                 
  383.         
  384.         if not matches:
  385.             raise DeviceError('Could not detect BSD names for %s. Try rebooting.' % self.name)
  386.         matches
  387.         pat = re.compile('(?P<m>\\d+)([a-z]+(?P<p>\\d+)){0,1}')
  388.         
  389.         def nums(x):
  390.             m = pat.search(x)
  391.             if m is None:
  392.                 return (10000, -1)
  393.             g = m.groupdict()
  394.             if g['p'] is None:
  395.                 g['p'] = 0
  396.             
  397.             return map(int, (g.get('m'), g.get('p')))
  398.  
  399.         
  400.         def dcmp(x, y):
  401.             x = x.rpartition('/')[-1]
  402.             y = y.rpartition('/')[-1]
  403.             x = nums(x)
  404.             y = nums(y)
  405.             if x[1] == 0 and y[1] > 0:
  406.                 return cmp(1, 2)
  407.             if x[1] > 0 and y[1] == 0:
  408.                 return cmp(2, 1)
  409.             ans = cmp(x[0], y[0])
  410.             return ans
  411.  
  412.         matches.sort(cmp = dcmp)
  413.         drives = {
  414.             'main': matches[0] }
  415.         if len(matches) > 1:
  416.             drives['carda'] = matches[1]
  417.         
  418.         if len(matches) > 2:
  419.             drives['cardb'] = matches[2]
  420.         
  421.         return drives
  422.  
  423.     
  424.     def osx_bsd_names(self):
  425.         drives = []
  426.         for i in range(3):
  427.             
  428.             try:
  429.                 drives = self._osx_bsd_names()
  430.                 if len(drives) > 1:
  431.                     return drives
  432.             except:
  433.                 if i == 2:
  434.                     raise 
  435.                 i == 2
  436.  
  437.             time.sleep(3)
  438.         
  439.         return drives
  440.  
  441.     
  442.     def open_osx(self):
  443.         drives = self.osx_bsd_names()
  444.         bsd_drives = dict(**drives)
  445.         drives = self.osx_sort_names(drives)
  446.         mount_map = usbobserver.get_mounted_filesystems()
  447.         for k, v in drives.items():
  448.             drives[k] = mount_map.get(v, None)
  449.         
  450.         if drives['main'] is None:
  451.             print bsd_drives, mount_map, drives
  452.             raise DeviceError(_('Unable to detect the %s mount point. Try rebooting.') % self.__class__.__name__)
  453.         drives['main'] is None
  454.         pat = self.OSX_MAIN_MEM_VOL_PAT
  455.         if pat is not None and len(drives) > 1 and 'main' in drives:
  456.             if pat.search(drives['main']) is None:
  457.                 main = drives['main']
  458.                 for x in ('carda', 'cardb'):
  459.                     if x in drives and pat.search(drives[x]):
  460.                         drives['main'] = drives.pop(x)
  461.                         drives[x] = main
  462.                         break
  463.                         continue
  464.                 
  465.             
  466.         
  467.         self._main_prefix = drives['main'] + os.sep
  468.         
  469.         def get_card_prefix(c):
  470.             ans = drives.get(c, None)
  471.             if ans is not None:
  472.                 ans += os.sep
  473.             
  474.             return ans
  475.  
  476.         self._card_a_prefix = get_card_prefix('carda')
  477.         self._card_b_prefix = get_card_prefix('cardb')
  478.  
  479.     
  480.     def find_device_nodes(self):
  481.         
  482.         def walk(base):
  483.             base = os.path.abspath(os.path.realpath(base))
  484.             for x in os.listdir(base):
  485.                 p = os.path.join(base, x)
  486.                 if os.path.islink(p) or not os.access(p, os.R_OK):
  487.                     continue
  488.                 
  489.                 isfile = os.path.isfile(p)
  490.                 yield (p, isfile)
  491.                 if not isfile:
  492.                     for y, q in walk(p):
  493.                         yield (y, q)
  494.                     
  495.             
  496.  
  497.         
  498.         def raw2num(raw):
  499.             raw = raw.lower()
  500.             if not raw.startswith('0x'):
  501.                 raw = '0x' + raw
  502.             
  503.             return int(raw, 16)
  504.  
  505.         d = os.path.dirname
  506.         j = os.path.join
  507.         usb_dir = None
  508.         
  509.         def test(val, attr):
  510.             q = getattr(self.detected_device, attr)
  511.             return q == val
  512.  
  513.         for x, isfile in walk('/sys/devices'):
  514.             if isfile and x.endswith('idVendor'):
  515.                 usb_dir = d(x)
  516.                 for y in ('idProduct', 'idVendor', 'bcdDevice'):
  517.                     if not os.access(j(usb_dir, y), os.R_OK):
  518.                         usb_dir = None
  519.                         continue
  520.                         continue
  521.                     ((None,),)
  522.                 
  523.                 
  524.                 e = lambda q: raw2num(open(j(usb_dir, q)).read())
  525.                 (ven, prod, bcd) = map(e, ('idVendor', 'idProduct', 'bcdDevice'))
  526.                 if not test(ven, 'idVendor') and test(prod, 'idProduct') and test(bcd, 'bcdDevice'):
  527.                     usb_dir = None
  528.                     continue
  529.                 else:
  530.                     break
  531.             test(bcd, 'bcdDevice')
  532.         
  533.         if usb_dir is None:
  534.             raise DeviceError(_('Unable to detect the %s disk drive.') % self.__class__.__name__)
  535.         usb_dir is None
  536.         devnodes = []
  537.         ok = { }
  538.         for x, isfile in walk(usb_dir):
  539.             if not isfile and '/block/' in x:
  540.                 parts = x.split('/')
  541.                 idx = parts.index('block')
  542.                 if idx == len(parts) - 2:
  543.                     sz = j(x, 'size')
  544.                     node = parts[idx + 1]
  545.                     
  546.                     try:
  547.                         exists = int(open(sz).read()) > 0
  548.                         if exists:
  549.                             node = self.find_largest_partition(x)
  550.                             ok[node] = True
  551.                         else:
  552.                             ok[node] = False
  553.                     except:
  554.                         (None, None, None)
  555.                         ok[node] = False
  556.  
  557.                     devnodes.append(node)
  558.                 
  559.             idx == len(parts) - 2
  560.         
  561.         devnodes += list(repeat(None, 3))
  562.         ans = []([ _[1] if ok.get(x, False) else None for x in devnodes[:3] ])
  563.         return self.linux_swap_drives(ans)
  564.  
  565.     
  566.     def linux_swap_drives(self, drives):
  567.         return drives
  568.  
  569.     
  570.     def node_mountpoint(self, node):
  571.         
  572.         def de_mangle(raw):
  573.             return raw.replace('\\040', ' ').replace('\\011', '\t').replace('\\012', '\n').replace('\\0134', '\\')
  574.  
  575.         for line in open('/proc/mounts').readlines():
  576.             line = line.split()
  577.             if line[0] == node:
  578.                 return de_mangle(line[1])
  579.         
  580.  
  581.     
  582.     def find_largest_partition(self, path):
  583.         node = path.split('/')[-1]
  584.         nodes = []
  585.         for x in glob.glob(path + '/' + node + '*'):
  586.             sz = x + '/size'
  587.             if not os.access(sz, os.R_OK):
  588.                 continue
  589.             
  590.             
  591.             try:
  592.                 sz = int(open(sz).read())
  593.             except:
  594.                 continue
  595.  
  596.             if sz > 0:
  597.                 nodes.append((x.split('/')[-1], sz))
  598.                 continue
  599.         
  600.         nodes.sort(cmp = (lambda x, y: cmp(x[1], y[1])))
  601.         if not nodes:
  602.             return node
  603.         return nodes[-1][0]
  604.  
  605.     
  606.     def open_linux(self):
  607.         
  608.         def mount(node, type):
  609.             mp = self.node_mountpoint(node)
  610.             if mp is not None:
  611.                 return (mp, 0)
  612.             if type == 'main':
  613.                 label = self.MAIN_MEMORY_VOLUME_LABEL
  614.             
  615.             if type == 'carda':
  616.                 label = self.STORAGE_CARD_VOLUME_LABEL
  617.             
  618.             if type == 'cardb':
  619.                 label = self.STORAGE_CARD2_VOLUME_LABEL
  620.                 if not label:
  621.                     label = self.STORAGE_CARD_VOLUME_LABEL + ' 2'
  622.                 
  623.             
  624.             extra = 0
  625.             while True:
  626.                 q = None if extra else ''
  627.                 if not os.path.exists('/media/' + label + q):
  628.                     break
  629.                 
  630.                 extra += 1
  631.             if extra:
  632.                 label += ' (%d)' % extra
  633.             
  634.             
  635.             def do_mount(node, label):
  636.                 cmd = 'calibre-mount-helper'
  637.                 if getattr(sys, 'frozen_path', False):
  638.                     cmd = os.path.join(sys.frozen_path, cmd)
  639.                 
  640.                 cmd = [
  641.                     cmd,
  642.                     'mount']
  643.                 
  644.                 try:
  645.                     p = subprocess.Popen(cmd + [
  646.                         node,
  647.                         '/media/' + label])
  648.                 except OSError:
  649.                     raise DeviceError(_('Could not find mount helper: %s.') % cmd[0])
  650.  
  651.                 while p.poll() is None:
  652.                     time.sleep(0.1)
  653.                 return p.returncode
  654.  
  655.             ret = do_mount(node, label)
  656.             if ret != 0:
  657.                 return (None, ret)
  658.             return (self.node_mountpoint(node) + '/', 0)
  659.  
  660.         (main, carda, cardb) = self.find_device_nodes()
  661.         if main is None:
  662.             raise DeviceError(_('Unable to detect the %s disk drive. Your  kernel is probably exporting a deprecated version of SYSFS.') % self.__class__.__name__)
  663.         main is None
  664.         self._linux_mount_map = { }
  665.         (mp, ret) = mount(main, 'main')
  666.         if mp is None:
  667.             raise DeviceError(_('Unable to mount main memory (Error code: %d)') % ret)
  668.         mp is None
  669.         if not mp.endswith('/'):
  670.             mp += '/'
  671.         
  672.         self._linux_mount_map[main] = mp
  673.         self._main_prefix = mp
  674.         cards = [
  675.             (carda, '_card_a_prefix', 'carda'),
  676.             (cardb, '_card_b_prefix', 'cardb')]
  677.         for card, prefix, typ in cards:
  678.             if card is None:
  679.                 continue
  680.             
  681.             (mp, ret) = mount(card, typ)
  682.             if mp is None:
  683.                 print >>sys.stderr, 'Unable to mount card (Error code: %d)' % ret
  684.                 continue
  685.             if not mp.endswith('/'):
  686.                 mp += '/'
  687.             
  688.             setattr(self, prefix, mp)
  689.             self._linux_mount_map[card] = mp
  690.         
  691.  
  692.     
  693.     def open(self):
  694.         time.sleep(5)
  695.         self._main_prefix = None
  696.         self._card_a_prefix = None
  697.         self._card_b_prefix = None
  698.         if islinux:
  699.             
  700.             try:
  701.                 self.open_linux()
  702.             except DeviceError:
  703.                 time.sleep(7)
  704.                 self.open_linux()
  705.             except:
  706.                 None<EXCEPTION MATCH>DeviceError
  707.             
  708.  
  709.         None<EXCEPTION MATCH>DeviceError
  710.         if iswindows:
  711.             
  712.             try:
  713.                 self.open_windows()
  714.             except DeviceError:
  715.                 time.sleep(7)
  716.                 self.open_windows()
  717.             except:
  718.                 None<EXCEPTION MATCH>DeviceError
  719.             
  720.  
  721.         None<EXCEPTION MATCH>DeviceError
  722.         if isosx:
  723.             
  724.             try:
  725.                 self.open_osx()
  726.             except DeviceError:
  727.                 time.sleep(7)
  728.                 self.open_osx()
  729.             except:
  730.                 None<EXCEPTION MATCH>DeviceError
  731.             
  732.  
  733.         None<EXCEPTION MATCH>DeviceError
  734.         self.post_open_callback()
  735.  
  736.     
  737.     def post_open_callback(self):
  738.         pass
  739.  
  740.     
  741.     def eject_windows(self):
  742.         plugins = plugins
  743.         import calibre.constants
  744.         Thread = Thread
  745.         import threading
  746.         (winutil, winutil_err) = plugins['winutil']
  747.         drives = []
  748.         for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):
  749.             x = getattr(self, x, None)
  750.             if x is not None:
  751.                 drives.append(x[0].upper())
  752.                 continue
  753.         
  754.         
  755.         def do_it(drives):
  756.             for d in drives:
  757.                 
  758.                 try:
  759.                     winutil.eject_drive(bytes(d)[0])
  760.                 continue
  761.                 continue
  762.  
  763.             
  764.  
  765.         t = Thread(target = do_it, args = [
  766.             drives])
  767.         t.daemon = True
  768.         t.start()
  769.         self._Device__save_win_eject_thread = t
  770.  
  771.     
  772.     def eject_osx(self):
  773.         for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):
  774.             x = getattr(self, x, None)
  775.             if x is not None:
  776.                 
  777.                 try:
  778.                     subprocess.Popen(self.OSX_EJECT_COMMAND + [
  779.                         x])
  780.  
  781.                 continue
  782.         
  783.  
  784.     
  785.     def eject_linux(self):
  786.         drives = self.find_device_nodes()
  787.         for drive in drives:
  788.             if drive:
  789.                 cmd = 'calibre-mount-helper'
  790.                 if getattr(sys, 'frozen_path', False):
  791.                     cmd = os.path.join(sys.frozen_path, cmd)
  792.                 
  793.                 cmd = [
  794.                     cmd,
  795.                     'eject']
  796.                 mp = getattr(self, '_linux_mount_map', { }).get(drive, 'dummy/')[:-1]
  797.                 
  798.                 try:
  799.                     subprocess.Popen(cmd + [
  800.                         drive,
  801.                         mp]).wait()
  802.  
  803.                 continue
  804.         
  805.  
  806.     
  807.     def eject(self):
  808.         if islinux:
  809.             
  810.             try:
  811.                 self.eject_linux()
  812.  
  813.         
  814.         if iswindows:
  815.             
  816.             try:
  817.                 self.eject_windows()
  818.  
  819.         
  820.         if isosx:
  821.             
  822.             try:
  823.                 self.eject_osx()
  824.  
  825.         
  826.         self._main_prefix = None
  827.         self._card_a_prefix = None
  828.         self._card_b_prefix = None
  829.  
  830.     
  831.     def linux_post_yank(self):
  832.         for drive, mp in getattr(self, '_linux_mount_map', { }).items():
  833.             if drive and mp:
  834.                 mp = mp[:-1]
  835.                 cmd = 'calibre-mount-helper'
  836.                 if getattr(sys, 'frozen_path', False):
  837.                     cmd = os.path.join(sys.frozen_path, cmd)
  838.                 
  839.                 cmd = [
  840.                     cmd,
  841.                     'cleanup']
  842.                 if mp and os.path.exists(mp):
  843.                     
  844.                     try:
  845.                         subprocess.Popen(cmd + [
  846.                             drive,
  847.                             mp]).wait()
  848.                     import traceback
  849.                     traceback.print_exc()
  850.  
  851.                 
  852.             os.path.exists(mp)
  853.         
  854.         self._linux_mount_map = { }
  855.  
  856.     
  857.     def post_yank_cleanup(self):
  858.         if islinux:
  859.             
  860.             try:
  861.                 self.linux_post_yank()
  862.             import traceback
  863.             traceback.print_exc()
  864.  
  865.         
  866.         self._main_prefix = None
  867.         self._card_a_prefix = None
  868.         self._card_b_prefix = None
  869.  
  870.     
  871.     def get_main_ebook_dir(self, for_upload = False):
  872.         return self.EBOOK_DIR_MAIN
  873.  
  874.     
  875.     def _sanity_check(self, on_card, files):
  876.         if on_card == 'carda' and not (self._card_a_prefix):
  877.             raise ValueError(_('The reader has no storage card in this slot.'))
  878.         not (self._card_a_prefix)
  879.         if on_card == 'cardb' and not (self._card_b_prefix):
  880.             raise ValueError(_('The reader has no storage card in this slot.'))
  881.         not (self._card_b_prefix)
  882.         if on_card and on_card not in ('carda', 'cardb'):
  883.             raise DeviceError(_('Selected slot: %s is not supported.') % on_card)
  884.         on_card not in ('carda', 'cardb')
  885.         if on_card == 'carda':
  886.             path = os.path.join(self._card_a_prefix, *self.EBOOK_DIR_CARD_A.split('/'))
  887.         elif on_card == 'cardb':
  888.             path = os.path.join(self._card_b_prefix, *self.EBOOK_DIR_CARD_B.split('/'))
  889.         else:
  890.             candidates = self.get_main_ebook_dir(for_upload = True)
  891.             if isinstance(candidates, basestring):
  892.                 candidates = [
  893.                     candidates]
  894.             
  895.             candidates = [ _[1] if x else self._main_prefix for x in candidates ]
  896.             existing = _[2]
  897.             path = existing[0]
  898.         
  899.         def get_size(obj):
  900.             path = getattr(obj, 'name', obj)
  901.             return os.path.getsize(path)
  902.  
  903.         sizes = [ get_size(f) for f in files ]
  904.         size = sum(sizes)
  905.         if not on_card and size > self.free_space()[0] - 2097152:
  906.             raise FreeSpaceError(_('There is insufficient free space in main memory'))
  907.         size > self.free_space()[0] - 2097152
  908.         if on_card == 'carda' and size > self.free_space()[1] - 1048576:
  909.             raise FreeSpaceError(_('There is insufficient free space on the storage card'))
  910.         size > self.free_space()[1] - 1048576
  911.         if on_card == 'cardb' and size > self.free_space()[2] - 1048576:
  912.             raise FreeSpaceError(_('There is insufficient free space on the storage card'))
  913.         size > self.free_space()[2] - 1048576
  914.         return path
  915.  
  916.     
  917.     def filename_callback(self, default, mi):
  918.         return default
  919.  
  920.     
  921.     def sanitize_path_components(self, components):
  922.         return components
  923.  
  924.     
  925.     def get_annotations(self, path_map):
  926.         return { }
  927.  
  928.     
  929.     def create_upload_path(self, path, mdata, fname, create_dirs = True):
  930.         path = os.path.abspath(path)
  931.         extra_components = []
  932.         special_tag = None
  933.         if mdata.tags:
  934.             for t in mdata.tags:
  935.                 if t.startswith(_('News')) or t.startswith('/'):
  936.                     special_tag = t
  937.                     break
  938.                     continue
  939.             
  940.         
  941.         settings = self.settings()
  942.         template = self.save_template()
  943.         if mdata.tags and _('News') in mdata.tags:
  944.             today = time.localtime()
  945.             template = '{title}_%d-%d-%d' % (today[0], today[1], today[2])
  946.         
  947.         if self.SUPPORTS_SUB_DIRS:
  948.             pass
  949.         use_subdirs = settings.use_subdirs
  950.         fname = sanitize(fname)
  951.         ext = os.path.splitext(fname)[1]
  952.         get_components = get_components
  953.         import calibre.library.save_to_disk
  954.         if not isinstance(template, unicode):
  955.             template = template.decode('utf-8')
  956.         
  957.         app_id = str(getattr(mdata, 'application_id', ''))
  958.         extra_components = get_components(template, mdata, fname, length = 250 - len(app_id) - 1)
  959.         if not extra_components:
  960.             extra_components.append(sanitize(self.filename_callback(fname, mdata)))
  961.         else:
  962.             extra_components[-1] = sanitize(self.filename_callback(extra_components[-1] + ext, mdata))
  963.         if extra_components[-1] and extra_components[-1][0] in ('.', '_'):
  964.             extra_components[-1] = 'x' + extra_components[-1][1:]
  965.         
  966.         if special_tag is not None:
  967.             name = extra_components[-1]
  968.             extra_components = []
  969.             tag = special_tag
  970.             if tag.startswith(_('News')):
  971.                 extra_components.append('News')
  972.             else:
  973.                 for c in tag.split('/'):
  974.                     c = sanitize(c)
  975.                     if not c:
  976.                         continue
  977.                     
  978.                     extra_components.append(c)
  979.                 
  980.             extra_components.append(name)
  981.         
  982.         if not use_subdirs:
  983.             extra_components = extra_components[-1:]
  984.         
  985.         
  986.         def remove_trailing_periods(x):
  987.             ans = x
  988.             while ans.endswith('.'):
  989.                 ans = ans[:-1].strip()
  990.             if not ans:
  991.                 ans = 'x'
  992.             
  993.             return ans
  994.  
  995.         extra_components = list(map(remove_trailing_periods, extra_components))
  996.         components = shorten_components_to(250 - len(path), extra_components)
  997.         components = self.sanitize_path_components(components)
  998.         filepath = os.path.join(path, *components)
  999.         filedir = os.path.dirname(filepath)
  1000.         if create_dirs and not os.path.exists(filedir):
  1001.             os.makedirs(filedir)
  1002.         
  1003.         return filepath
  1004.  
  1005.  
  1006.