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