Esempio n. 1
0
 def _update_driveinfo_file(self, prefix, location_code, name=None):
     from calibre.utils.config import from_json, to_json
     if os.path.exists(os.path.join(prefix, self.DRIVEINFO)):
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'rb') as f:
             try:
                 driveinfo = json.loads(f.read(), object_hook=from_json)
             except:
                 driveinfo = None
             driveinfo = self._update_driveinfo_record(driveinfo, prefix,
                                                       location_code, name)
         data = json.dumps(driveinfo, default=to_json)
         if not isinstance(data, bytes):
             data = data.encode('utf-8')
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f:
             f.write(data)
             fsync(f)
     else:
         driveinfo = self._update_driveinfo_record({}, prefix, location_code, name)
         data = json.dumps(driveinfo, default=to_json)
         if not isinstance(data, bytes):
             data = data.encode('utf-8')
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f:
             f.write(data)
             fsync(f)
     return driveinfo
Esempio n. 2
0
 def _update_driveinfo_file(self, prefix, location_code, name=None):
     from calibre.utils.config import from_json, to_json
     if os.path.exists(os.path.join(prefix, self.DRIVEINFO)):
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'rb') as f:
             try:
                 driveinfo = json.loads(f.read(), object_hook=from_json)
             except:
                 driveinfo = None
             driveinfo = self._update_driveinfo_record(
                 driveinfo, prefix, location_code, name)
         data = json.dumps(driveinfo, default=to_json)
         if not isinstance(data, bytes):
             data = data.encode('utf-8')
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f:
             f.write(data)
             fsync(f)
     else:
         driveinfo = self._update_driveinfo_record({}, prefix,
                                                   location_code, name)
         data = json.dumps(driveinfo, default=to_json)
         if not isinstance(data, bytes):
             data = data.encode('utf-8')
         with lopen(os.path.join(prefix, self.DRIVEINFO), 'wb') as f:
             f.write(data)
             fsync(f)
     return driveinfo
Esempio n. 3
0
 def put_file(self, infile, path, replace_file=False, end_session=True):
     path = self.munge_path(path)
     close = False
     if not hasattr(infile, 'read'):
         infile, close = lopen(infile, 'rb'), True
     infile.seek(0)
     if os.path.isdir(path):
         path = os.path.join(path, infile.name)
     if not replace_file and os.path.exists(path):
         raise PathError('File already exists: ' + path)
     dest, actual_path = case_preserving_open_file(path)
     with dest:
         try:
             shutil.copyfileobj(infile, dest)
         except OSError:
             print('WARNING: First attempt to send file to device failed')
             time.sleep(0.2)
             infile.seek(0)
             dest.seek(0)
             dest.truncate()
             shutil.copyfileobj(infile, dest)
         fsync(dest)
         # if not check_transfer(infile, dest): raise Exception('Transfer failed')
     if close:
         infile.close()
     return actual_path
Esempio n. 4
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         with open('%s.jpg' % os.path.join(path, filename),
                   'wb') as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 5
0
    def upload_book_cover(self, connection, book, source_id):
        debug_print('PRST1: Uploading/Refreshing Cover for ' + book.title)
        if (not book.thumbnail or isinstance(book.thumbnail, ImageWrapper) or
                not book.thumbnail[-1]):
            # If the thumbnail is an ImageWrapper instance, it refers to a book
            # not in the calibre library
            return
        cursor = connection.cursor()

        thumbnail_path = THUMBPATH%book.bookId

        prefix = self._main_prefix if source_id is 0 else self._card_a_prefix
        thumbnail_file_path = os.path.join(prefix, *thumbnail_path.split('/'))
        thumbnail_dir_path = os.path.dirname(thumbnail_file_path)
        if not os.path.exists(thumbnail_dir_path):
            os.makedirs(thumbnail_dir_path)

        with lopen(thumbnail_file_path, 'wb') as f:
            f.write(book.thumbnail[-1])
            fsync(f)

        query = 'UPDATE books SET thumbnail = ? WHERE _id = ?'
        t = (thumbnail_path, book.bookId,)
        cursor.execute(query, t)

        connection.commit()
        cursor.close()
Esempio n. 6
0
    def upload_book_cover(self, connection, book, source_id):
        debug_print('PRST1: Uploading/Refreshing Cover for ' + book.title)
        if (not book.thumbnail or isinstance(book.thumbnail, ImageWrapper)
                or not book.thumbnail[-1]):
            # If the thumbnail is an ImageWrapper instance, it refers to a book
            # not in the calibre library
            return
        cursor = connection.cursor()

        thumbnail_path = THUMBPATH % book.bookId

        prefix = self._main_prefix if source_id is 0 else self._card_a_prefix
        thumbnail_file_path = os.path.join(prefix, *thumbnail_path.split('/'))
        thumbnail_dir_path = os.path.dirname(thumbnail_file_path)
        if not os.path.exists(thumbnail_dir_path):
            os.makedirs(thumbnail_dir_path)

        with open(thumbnail_file_path, 'wb') as f:
            f.write(book.thumbnail[-1])
            fsync(f)

        query = 'UPDATE books SET thumbnail = ? WHERE _id = ?'
        t = (
            thumbnail_path,
            book.bookId,
        )
        cursor.execute(query, t)

        connection.commit()
        cursor.close()
Esempio n. 7
0
    def write(self):
        from lxml import etree

        for i, path in self.paths.items():
            self.move_playlists_to_bottom()
            self.cleanup_whitespace(i)
            raw = etree.tostring(self.roots[i], encoding='UTF-8',
                    xml_declaration=True)
            raw = raw.replace("<?xml version='1.0' encoding='UTF-8'?>",
                    '<?xml version="1.0" encoding="UTF-8"?>')
            with lopen(path, 'wb') as f:
                f.write(raw)
                fsync(f)

        for i, path in self.ext_paths.items():
            try:
                raw = etree.tostring(self.ext_roots[i], encoding='UTF-8',
                    xml_declaration=True)
            except:
                continue
            raw = raw.replace("<?xml version='1.0' encoding='UTF-8'?>",
                    '<?xml version="1.0" encoding="UTF-8"?>')
            with lopen(path, 'wb') as f:
                f.write(raw)
                fsync(f)
Esempio n. 8
0
    def upload_cover(self, path, filename, metadata, filepath):
        try:
            from PIL import Image, ImageDraw
            Image, ImageDraw
        except ImportError:
            import Image, ImageDraw

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = lopen(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (96, 144), 'black')
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((96, 144), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((96-x)/2, (144-y)/2))

            draw = ImageDraw.Draw(cover)
            draw.text((1, 15), metadata.get('title', _('Unknown')).encode('ascii', 'ignore'))
            draw.text((1, 115), metadata.get('authors', _('Unknown')).encode('ascii', 'ignore'))

        data = cStringIO.StringIO()
        cover.save(data, 'JPEG')
        coverdata = data.getvalue()

        with lopen('%s.jpg' % os.path.join(path, filename), 'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)
Esempio n. 9
0
    def upload_cover(self, path, filename, metadata, filepath):
        try:
            from PIL import Image, ImageDraw
            Image, ImageDraw
        except ImportError:
            import Image, ImageDraw

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = lopen(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (96, 144), 'black')
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((96, 144), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((96 - x) / 2, (144 - y) / 2))

            draw = ImageDraw.Draw(cover)
            draw.text((1, 15),
                      metadata.get('title',
                                   _('Unknown')).encode('ascii', 'ignore'))
            draw.text((1, 115),
                      metadata.get('authors',
                                   _('Unknown')).encode('ascii', 'ignore'))

        data = cStringIO.StringIO()
        cover.save(data, 'JPEG')
        coverdata = data.getvalue()

        with lopen('%s.jpg' % os.path.join(path, filename), 'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)
Esempio n. 10
0
 def sync_cover_thumbnails(self):
     import shutil
     # See https://www.mobileread.com/forums/showthread.php?t=329945
     # for why this is needed
     if DEBUG:
         prints('Syncing cover thumbnails to workaround amazon cover bug')
     dest_dir = self.amazon_system_thumbnails_dir()
     src_dir = self.amazon_cover_bug_cache_dir()
     if not os.path.exists(dest_dir) or not os.path.exists(src_dir):
         return
     count = 0
     for name, src_stat_result in get_files_in(src_dir):
         dest_path = os.path.join(dest_dir, name)
         try:
             dest_stat_result = os.lstat(dest_path)
         except OSError:
             needs_sync = True
         else:
             needs_sync = src_stat_result.st_size != dest_stat_result.st_size
         if needs_sync:
             count += 1
             if DEBUG:
                 prints('Restoring cover thumbnail:', name)
             with lopen(os.path.join(src_dir, name),
                        'rb') as src, lopen(dest_path, 'wb') as dest:
                 shutil.copyfileobj(src, dest)
                 fsync(dest)
     if DEBUG:
         prints(
             'Restored {} cover thumbnails that were destroyed by Amazon'.
             format(count))
Esempio n. 11
0
 def put_file(self, infile, path, replace_file=False, end_session=True):
     path = self.munge_path(path)
     close = False
     if not hasattr(infile, 'read'):
         infile, close = lopen(infile, 'rb'), True
     infile.seek(0)
     if os.path.isdir(path):
         path = os.path.join(path, infile.name)
     if not replace_file and os.path.exists(path):
         raise PathError('File already exists: ' + path)
     dest, actual_path = case_preserving_open_file(path)
     with dest:
         try:
             shutil.copyfileobj(infile, dest)
         except IOError:
             print('WARNING: First attempt to send file to device failed')
             time.sleep(0.2)
             infile.seek(0)
             dest.seek(0)
             dest.truncate()
             shutil.copyfileobj(infile, dest)
         fsync(dest)
         # if not check_transfer(infile, dest): raise Exception('Transfer failed')
     if close:
         infile.close()
     return actual_path
Esempio n. 12
0
    def write(self):
        from lxml import etree

        for i, path in self.paths.items():
            self.move_playlists_to_bottom()
            self.cleanup_whitespace(i)
            raw = etree.tostring(self.roots[i], encoding='UTF-8',
                    xml_declaration=True)
            raw = raw.replace("<?xml version='1.0' encoding='UTF-8'?>",
                    '<?xml version="1.0" encoding="UTF-8"?>')
            with open(path, 'wb') as f:
                f.write(raw)
                fsync(f)

        for i, path in self.ext_paths.items():
            try:
                raw = etree.tostring(self.ext_roots[i], encoding='UTF-8',
                    xml_declaration=True)
            except:
                continue
            raw = raw.replace("<?xml version='1.0' encoding='UTF-8'?>",
                    '<?xml version="1.0" encoding="UTF-8"?>')
            with open(path, 'wb') as f:
                f.write(raw)
                fsync(f)
Esempio n. 13
0
    def write_apnx(self, mobi_file_path, apnx_path, accurate=True, page_count=0):
        '''
        If you want a fixed number of pages (such as from a custom column) then
        pass in a value to page_count, otherwise a count will be estimated
        using either the fast or accurate algorithm.
        '''
        import uuid
        apnx_meta = { 'guid': str(uuid.uuid4()).replace('-', '')[:8], 'asin':
                '', 'cdetype': 'EBOK', 'format': 'MOBI_7', 'acr': '' }

        with open(mobi_file_path, 'rb') as mf:
            ident = PdbHeaderReader(mf).identity()
            if ident != 'BOOKMOBI':
                # Check that this is really a MOBI file.
                raise Exception(_('Not a valid MOBI file. Reports identity of %s') % ident)
            apnx_meta['acr'] = str(PdbHeaderReader(mf).name())

        # We'll need the PDB name, the MOBI version, and some metadata to make FW 3.4 happy with KF8 files...
        with open(mobi_file_path, 'rb') as mf:
            mh = MetadataHeader(mf, default_log)
            if mh.mobi_version == 8:
                apnx_meta['format'] = 'MOBI_8'
            else:
                apnx_meta['format'] = 'MOBI_7'
            if mh.exth is None or not mh.exth.cdetype:
                apnx_meta['cdetype'] = 'EBOK'
            else:
                apnx_meta['cdetype'] = str(mh.exth.cdetype)
            if mh.exth is None or not mh.exth.uuid:
                apnx_meta['asin'] = ''
            else:
                apnx_meta['asin'] = str(mh.exth.uuid)

        # Get the pages depending on the chosen parser
        pages = []
        if page_count:
            pages = self.get_pages_exact(mobi_file_path, page_count)
        else:
            if accurate:
                try:
                    pages = self.get_pages_accurate(mobi_file_path)
                except:
                    # Fall back to the fast parser if we can't
                    # use the accurate one. Typically this is
                    # due to the file having DRM.
                    pages = self.get_pages_fast(mobi_file_path)
            else:
                pages = self.get_pages_fast(mobi_file_path)

        if not pages:
            raise Exception(_('Could not generate page mapping.'))

        # Generate the APNX file from the page mapping.
        apnx = self.generate_apnx(pages, apnx_meta)

        # Write the APNX.
        with open(apnx_path, 'wb') as apnxf:
            apnxf.write(apnx)
            fsync(apnxf)
Esempio n. 14
0
 def write_prefix(prefix, listid):
     if (prefix is not None and len(booklists) > listid and
             isinstance(booklists[listid], self.booklist_class)):
         if not os.path.exists(prefix):
             os.makedirs(self.normalize_path(prefix))
         with lopen(self.normalize_path(os.path.join(prefix, self.METADATA_CACHE)), 'wb') as f:
             json_codec.encode_to_file(f, booklists[listid])
             fsync(f)
Esempio n. 15
0
 def write_prefix(prefix, listid):
     if (prefix is not None and len(booklists) > listid and
             isinstance(booklists[listid], self.booklist_class)):
         if not os.path.exists(prefix):
             os.makedirs(self.normalize_path(prefix))
         with lopen(self.normalize_path(os.path.join(prefix, self.METADATA_CACHE)), 'wb') as f:
             json_codec.encode_to_file(f, booklists[listid])
             fsync(f)
Esempio n. 16
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, "thumbnail", None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with open("%s_6090.t2b" % os.path.join(path, filename), "wb") as t2bfile:
         t2b.write_t2b(t2bfile, coverdata)
         fsync(t2bfile)
Esempio n. 17
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with open('%s_6090.t2b' % os.path.join(path, filename), 'wb') as t2bfile:
         t2b.write_t2b(t2bfile, coverdata)
         fsync(t2bfile)
Esempio n. 18
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, "thumbnail", None)
     if coverdata and coverdata[2]:
         dirpath = os.path.join(path, ".thumbnail")
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
         with open(os.path.join(dirpath, filename + ".jpg"), "wb") as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 19
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, "thumbnail", None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with open("%s.thn" % filepath, "wb") as thnfile:
         t4b.write_t4b(thnfile, coverdata)
         fsync(thnfile)
Esempio n. 20
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         dirpath = os.path.join(path, '.thumbnail')
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
         with lopen(os.path.join(dirpath, filename+'.jpg'), 'wb') as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 21
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with lopen('%s.thn' % filepath, 'wb') as thnfile:
         t4b.write_t4b(thnfile, coverdata)
         fsync(thnfile)
Esempio n. 22
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         dirpath = os.path.join(path, '.thumbnail')
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
         with open(os.path.join(dirpath, filename+'.jpg'), 'wb') as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 23
0
    def upload_cover(self, path, filename, metadata, filepath):

        from PIL import Image, ImageDraw

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(io.BytesIO(coverdata[2]))
        else:
            coverdata = lopen(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (120, 160), 'black')
            im = Image.open(io.BytesIO(coverdata))
            im.thumbnail((120, 160), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((120 - x) / 2, (160 - y) / 2))

            draw = ImageDraw.Draw(cover)
            draw.text((1, 10),
                      metadata.get('title',
                                   _('Unknown')).encode('ascii', 'ignore'))
            draw.text((1, 140),
                      metadata.get('authors',
                                   _('Unknown'))[0].encode('ascii', 'ignore'))

        data = io.BytesIO()
        cover.save(data, 'JPEG')
        coverdata = data.getvalue()

        with lopen(os.path.join(path, 'coverCache', filename + '-medium.jpg'),
                   'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(io.BytesIO(coverdata[2]))
        else:
            coverdata = lopen(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (52, 69), 'black')
            im = Image.open(io.BytesIO(coverdata))
            im.thumbnail((52, 69), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((52 - x) // 2, (69 - y) // 2))

        cover2 = cover.resize((52, 69), Image.ANTIALIAS).convert('RGB')

        data = io.BytesIO()
        cover2.save(data, 'JPEG')
        coverdata = data.getvalue()

        with lopen(os.path.join(path, 'coverCache', filename + '-small.jpg'),
                   'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)
Esempio n. 24
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with lopen('%s_6090.t2b' % os.path.join(path, filename), 'wb') as t2bfile:
         t2b.write_t2b(t2bfile, coverdata)
         fsync(t2bfile)
Esempio n. 25
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         coverdata = coverdata[2]
     else:
         coverdata = None
     with lopen('%s.thn' % filepath, 'wb') as thnfile:
         t4b.write_t4b(thnfile, coverdata)
         fsync(thnfile)
Esempio n. 26
0
    def upload_cover(self, path, filename, metadata, filepath):

        try:
            from PIL import Image, ImageDraw

            Image, ImageDraw
        except ImportError:
            import Image, ImageDraw

        coverdata = getattr(metadata, "thumbnail", None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = open(I("library.png"), "rb").read()

            cover = Image.new("RGB", (120, 160), "black")
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((120, 160), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((120 - x) / 2, (160 - y) / 2))

            draw = ImageDraw.Draw(cover)
            draw.text((1, 10), metadata.get("title", _("Unknown")).encode("ascii", "ignore"))
            draw.text((1, 140), metadata.get("authors", _("Unknown"))[0].encode("ascii", "ignore"))

        data = cStringIO.StringIO()
        cover.save(data, "JPEG")
        coverdata = data.getvalue()

        with open(os.path.join(path, "coverCache", filename + "-medium.jpg"), "wb") as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)

        coverdata = getattr(metadata, "thumbnail", None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = open(I("library.png"), "rb").read()

            cover = Image.new("RGB", (52, 69), "black")
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((52, 69), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((52 - x) / 2, (69 - y) / 2))

        cover2 = cover.resize((52, 69), Image.ANTIALIAS).convert("RGB")

        data = cStringIO.StringIO()
        cover2.save(data, "JPEG")
        coverdata = data.getvalue()

        with open(os.path.join(path, "coverCache", filename + "-small.jpg"), "wb") as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)
Esempio n. 27
0
    def upload_cover(self, path, filename, metadata, filepath):

        try:
            from PIL import Image, ImageDraw
            Image, ImageDraw
        except ImportError:
            import Image, ImageDraw

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = open(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (120,160), 'black')
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((120, 160), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((120-x)/2, (160-y)/2))

            draw = ImageDraw.Draw(cover)
            draw.text((1, 10), metadata.get('title', _('Unknown')).encode('ascii', 'ignore'))
            draw.text((1, 140), metadata.get('authors', _('Unknown'))[0].encode('ascii', 'ignore'))

        data = cStringIO.StringIO()
        cover.save(data, 'JPEG')
        coverdata = data.getvalue()

        with open(os.path.join(path, 'coverCache', filename + '-medium.jpg'), 'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)

        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = Image.open(cStringIO.StringIO(coverdata[2]))
        else:
            coverdata = open(I('library.png'), 'rb').read()

            cover = Image.new('RGB', (52,69), 'black')
            im = Image.open(cStringIO.StringIO(coverdata))
            im.thumbnail((52, 69), Image.ANTIALIAS)

            x, y = im.size
            cover.paste(im, ((52-x)/2, (69-y)/2))

        cover2 = cover.resize((52, 69), Image.ANTIALIAS).convert('RGB')

        data = cStringIO.StringIO()
        cover2.save(data, 'JPEG')
        coverdata = data.getvalue()

        with open(os.path.join(path, 'coverCache', filename +
            '-small.jpg'), 'wb') as coverfile:
            coverfile.write(coverdata)
            fsync(coverfile)
Esempio n. 28
0
    def upload_kindle_thumbnail(self, metadata, filepath):
        coverdata = getattr(metadata, 'thumbnail', None)
        if not coverdata or not coverdata[2]:
            return

        tp = self.thumbpath_from_filepath(filepath)
        if tp:
            with lopen(tp, 'wb') as f:
                f.write(coverdata[2])
                fsync(f)
Esempio n. 29
0
 def upload_cover(self, path, filename, metadata, filepath):
     if metadata.thumbnail and metadata.thumbnail[-1]:
         cfilepath = filepath.replace("/", os.sep)
         cfilepath = cfilepath.replace(os.sep + "books" + os.sep, os.sep + "covers" + os.sep, 1)
         pdir = os.path.dirname(cfilepath)
         if not os.path.exists(pdir):
             os.makedirs(pdir)
         with open(cfilepath + ".jpg", "wb") as f:
             f.write(metadata.thumbnail[-1])
             fsync(f)
Esempio n. 30
0
    def upload_kindle_thumbnail(self, metadata, filepath):
        coverdata = getattr(metadata, 'thumbnail', None)
        if not coverdata or not coverdata[2]:
            return

        tp = self.thumbpath_from_filepath(filepath)
        if tp:
            with lopen(tp, 'wb') as f:
                f.write(coverdata[2])
                fsync(f)
Esempio n. 31
0
 def upload_cover(self, path, filename, metadata, filepath):
     if metadata.thumbnail and metadata.thumbnail[-1]:
         cfilepath = filepath.replace('/', os.sep)
         cfilepath = cfilepath.replace(os.sep+'books'+os.sep,
                 os.sep+'covers'+os.sep, 1)
         pdir = os.path.dirname(cfilepath)
         if not os.path.exists(pdir):
             os.makedirs(pdir)
         with open(cfilepath+'.jpg', 'wb') as f:
             f.write(metadata.thumbnail[-1])
             fsync(f)
Esempio n. 32
0
 def upload_cover(self, path, filename, metadata, filepath):
     if metadata.thumbnail and metadata.thumbnail[-1]:
         cfilepath = filepath.replace('/', os.sep)
         cfilepath = cfilepath.replace(os.sep + 'books' + os.sep,
                                       os.sep + 'covers' + os.sep, 1)
         pdir = os.path.dirname(cfilepath)
         if not os.path.exists(pdir):
             os.makedirs(pdir)
         with lopen(cfilepath + '.jpg', 'wb') as f:
             f.write(metadata.thumbnail[-1])
             fsync(f)
Esempio n. 33
0
    def upload_kindle_thumbnail(self, metadata, filepath):
        from calibre.utils.logging import default_log
        coverdata = getattr(metadata, 'thumbnail', None)
        if not coverdata or not coverdata[2]:
            return
        thumb_dir = os.path.join(self._main_prefix, 'system', 'thumbnails')
        if not os.path.exists(thumb_dir): return

        from calibre.ebooks.mobi.reader.headers import MetadataHeader
        with lopen(filepath, 'rb') as f:
            mh = MetadataHeader(f, default_log)
        if mh.exth is None or not mh.exth.uuid or not mh.exth.cdetype:
            return
        thumbfile = os.path.join(thumb_dir,
                'thumbnail_{uuid}_{cdetype}_portrait.jpg'.format(
                    uuid=mh.exth.uuid, cdetype=mh.exth.cdetype))
        with open(thumbfile, 'wb') as f:
            f.write(coverdata[2])
            fsync(f)
Esempio n. 34
0
    def upload_kindle_thumbnail(self, metadata, filepath):
        from calibre.utils.logging import default_log
        coverdata = getattr(metadata, 'thumbnail', None)
        if not coverdata or not coverdata[2]:
            return
        thumb_dir = os.path.join(self._main_prefix, 'system', 'thumbnails')
        if not os.path.exists(thumb_dir): return

        from calibre.ebooks.mobi.reader.headers import MetadataHeader
        with lopen(filepath, 'rb') as f:
            mh = MetadataHeader(f, default_log)
        if mh.exth is None or not mh.exth.uuid or not mh.exth.cdetype:
            return
        thumbfile = os.path.join(
            thumb_dir, 'thumbnail_{uuid}_{cdetype}_portrait.jpg'.format(
                uuid=mh.exth.uuid, cdetype=mh.exth.cdetype))
        with open(thumbfile, 'wb') as f:
            f.write(coverdata[2])
            fsync(f)
Esempio n. 35
0
    def upload_kindle_thumbnail(self, metadata, filepath):
        coverdata = getattr(metadata, 'thumbnail', None)
        if not coverdata or not coverdata[2]:
            return

        tp = self.thumbpath_from_filepath(filepath)
        if tp:
            with lopen(tp, 'wb') as f:
                f.write(coverdata[2])
                fsync(f)
            cache_dir = self.amazon_cover_bug_cache_dir()
            try:
                os.mkdir(cache_dir)
            except EnvironmentError:
                pass
            with lopen(os.path.join(cache_dir, os.path.basename(tp)),
                       'wb') as f:
                f.write(coverdata[2])
                fsync(f)
Esempio n. 36
0
    def upload_cover(self, path, filename, metadata, filepath):
        from calibre.ebooks.covers import calibre_cover2
        from calibre.utils.img import scale_image
        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = coverdata[2]
        else:
            cover = calibre_cover2(metadata.get('title', _('Unknown')),
                    metadata.get('authors', _('Unknown')))

        cover = scale_image(cover, width=self.THUMBNAIL_HEIGHT,
                height=self.THUMBNAIL_HEIGHT, as_png=True)[-1]

        cpath = self.alex_cpath(os.path.join(path, filename))
        cdir = os.path.dirname(cpath)
        if not os.path.exists(cdir):
            os.makedirs(cdir)
        with lopen(cpath, 'wb') as coverfile:
            coverfile.write(cover)
            fsync(coverfile)
Esempio n. 37
0
    def upload_cover(self, path, filename, metadata, filepath):
        from calibre.ebooks import calibre_cover
        from calibre.utils.magick.draw import thumbnail
        coverdata = getattr(metadata, 'thumbnail', None)
        if coverdata and coverdata[2]:
            cover = coverdata[2]
        else:
            cover = calibre_cover(metadata.get('title', _('Unknown')),
                    metadata.get('authors', _('Unknown')))

        cover = thumbnail(cover, width=self.THUMBNAIL_HEIGHT,
                height=self.THUMBNAIL_HEIGHT, fmt='png')[-1]

        cpath = self.alex_cpath(os.path.join(path, filename))
        cdir = os.path.dirname(cpath)
        if not os.path.exists(cdir):
            os.makedirs(cdir)
        with open(cpath, 'wb') as coverfile:
            coverfile.write(cover)
            fsync(coverfile)
Esempio n. 38
0
 def write_cache(prefix):
     try:
         cachep = os.path.join(prefix, *(CACHE_XML.split('/')))
         if not os.path.exists(cachep):
             dname = os.path.dirname(cachep)
             if not os.path.exists(dname):
                 try:
                     os.makedirs(dname, mode=0777)
                 except:
                     time.sleep(5)
                     os.makedirs(dname, mode=0777)
             with lopen(cachep, 'wb') as f:
                 f.write(u'''<?xml version="1.0" encoding="UTF-8"?>
                     <cache xmlns="http://www.kinoma.com/FskCache/1">
                     </cache>
                     '''.encode('utf8'))
                 fsync(f)
         return True
     except:
         import traceback
         traceback.print_exc()
     return False
Esempio n. 39
0
 def write_cache(prefix):
     try:
         cachep = os.path.join(prefix, *(CACHE_XML.split('/')))
         if not os.path.exists(cachep):
             dname = os.path.dirname(cachep)
             if not os.path.exists(dname):
                 try:
                     os.makedirs(dname, mode=0777)
                 except:
                     time.sleep(5)
                     os.makedirs(dname, mode=0777)
             with open(cachep, 'wb') as f:
                 f.write(u'''<?xml version="1.0" encoding="UTF-8"?>
                     <cache xmlns="http://www.kinoma.com/FskCache/1">
                     </cache>
                     '''.encode('utf8'))
                 fsync(f)
         return True
     except:
         import traceback
         traceback.print_exc()
     return False
Esempio n. 40
0
    def __init__(self, paths, ext_paths, prefixes, use_author_sort):
        from lxml import etree

        if DEBUG:
            debug_print("Building XMLCache...", paths)
        self.paths = paths
        self.prefixes = prefixes
        self.use_author_sort = use_author_sort

        # Parse XML files {{{
        parser = etree.XMLParser(recover=True)
        self.roots = {}
        for source_id, path in paths.items():
            if source_id == 0:
                if not os.path.exists(path):
                    raise DeviceError(
                        ("The SONY XML cache %r does not exist. Try" " disconnecting and reconnecting your reader.")
                        % repr(path)
                    )
                with open(path, "rb") as f:
                    raw = f.read()
            else:
                raw = EMPTY_CARD_CACHE
                if os.access(path, os.R_OK):
                    with open(path, "rb") as f:
                        raw = f.read()

            self.roots[source_id] = etree.fromstring(
                xml_to_unicode(raw, strip_encoding_pats=True, assume_utf8=True, verbose=DEBUG)[0], parser=parser
            )
            if self.roots[source_id] is None:
                raise Exception(
                    ("The SONY database at %r is corrupted. Try " " disconnecting and reconnecting your reader.") % path
                )

        self.ext_paths, self.ext_roots = {}, {}
        for source_id, path in ext_paths.items():
            if not os.path.exists(path):
                try:
                    with open(path, "wb") as f:
                        f.write(EMPTY_EXT_CACHE)
                        fsync(f)
                except:
                    pass
            if os.access(path, os.W_OK):
                try:
                    with open(path, "rb") as f:
                        self.ext_roots[source_id] = etree.fromstring(
                            xml_to_unicode(f.read(), strip_encoding_pats=True, assume_utf8=True, verbose=DEBUG)[0],
                            parser=parser,
                        )
                        self.ext_paths[source_id] = path
                except:
                    pass

        # }}}

        recs = self.roots[0].xpath('//*[local-name()="records"]')
        if not recs:
            raise DeviceError(
                "The SONY XML database is corrupted (no"
                " <records>). Try disconnecting an reconnecting"
                " your reader."
            )
        self.record_roots = {}
        self.record_roots.update(self.roots)
        self.record_roots[0] = recs[0]

        self.detect_namespaces()
        debug_print("Done building XMLCache...")
Esempio n. 41
0
    def __init__(self, paths, ext_paths, prefixes, use_author_sort):
        from lxml import etree

        if DEBUG:
            debug_print('Building XMLCache...', paths)
        self.paths = paths
        self.prefixes = prefixes
        self.use_author_sort = use_author_sort

        # Parse XML files {{{
        parser = etree.XMLParser(recover=True)
        self.roots = {}
        for source_id, path in paths.items():
            if source_id == 0:
                if not os.path.exists(path):
                    raise DeviceError(('The SONY XML cache %r does not exist. Try'
                        ' disconnecting and reconnecting your reader.')%repr(path))
                with lopen(path, 'rb') as f:
                    raw = f.read()
            else:
                raw = EMPTY_CARD_CACHE
                if os.access(path, os.R_OK):
                    with lopen(path, 'rb') as f:
                        raw = f.read()

            self.roots[source_id] = etree.fromstring(xml_to_unicode(
                        raw, strip_encoding_pats=True, assume_utf8=True,
                        verbose=DEBUG)[0],
                        parser=parser)
            if self.roots[source_id] is None:
                raise Exception(('The SONY database at %r is corrupted. Try '
                        ' disconnecting and reconnecting your reader.')%path)

        self.ext_paths, self.ext_roots = {}, {}
        for source_id, path in ext_paths.items():
            if not os.path.exists(path):
                try:
                    with lopen(path, 'wb') as f:
                        f.write(EMPTY_EXT_CACHE)
                        fsync(f)
                except:
                    pass
            if os.access(path, os.W_OK):
                try:
                    with lopen(path, 'rb') as f:
                        self.ext_roots[source_id] = etree.fromstring(
                                xml_to_unicode(f.read(),
                                    strip_encoding_pats=True, assume_utf8=True,
                                    verbose=DEBUG)[0], parser=parser)
                        self.ext_paths[source_id] = path
                except:
                    pass

        # }}}

        recs = self.roots[0].xpath('//*[local-name()="records"]')
        if not recs:
            raise DeviceError('The SONY XML database is corrupted (no'
                    ' <records>). Try disconnecting an reconnecting'
                    ' your reader.')
        self.record_roots = {}
        self.record_roots.update(self.roots)
        self.record_roots[0] = recs[0]

        self.detect_namespaces()
        debug_print('Done building XMLCache...')
Esempio n. 42
0
def main():
    from calibre.utils.terminal import geometry
    cols = geometry()[0]

    parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+
            "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"+
    "For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
    parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
                    "The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
    dest="log_packets", action="store_true", default=False)
    parser.remove_option("-h")
    parser.disable_interspersed_args() # Allow unrecognized options
    options, args = parser.parse_args()

    if len(args) < 1:
        parser.print_help()
        return 1

    command = args[0]
    args = args[1:]
    dev = None
    scanner = DeviceScanner()
    scanner.scan()
    connected_devices = []

    for d in device_plugins():
        try:
            d.startup()
        except:
            print ('Startup failed for device plugin: %s'%d)
        if d.MANAGES_DEVICE_PRESENCE:
            cd = d.detect_managed_devices(scanner.devices)
            if cd is not None:
                connected_devices.append((cd, d))
                dev = d
                break
            continue
        ok, det = scanner.is_device_connected(d)
        if ok:
            dev = d
            dev.reset(log_packets=options.log_packets, detected_device=det)
            connected_devices.append((det, dev))

    if dev is None:
        print >>sys.stderr, 'Unable to find a connected ebook reader.'
        shutdown_plugins()
        return 1

    for det, d in connected_devices:
        try:
            d.open(det, None)
        except:
            continue
        else:
            dev = d
            d.specialize_global_preferences(device_prefs)
            break


    try:
        if command == "df":
            total = dev.total_space(end_session=False)
            free = dev.free_space()
            where = ("Memory", "Card A", "Card B")
            print "Filesystem\tSize \tUsed \tAvail \tUse%"
            for i in range(3):
                print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
                                                                            str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
        elif command == 'eject':
            dev.eject()
        elif command == "books":
            print "Books in main memory:"
            for book in dev.books():
                print book
            print "\nBooks on storage carda:"
            for book in dev.books(oncard='carda'): print book
            print "\nBooks on storage cardb:"
            for book in dev.books(oncard='cardb'): print book
        elif command == "mkdir":
            parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/")
            if len(args) != 1:
                parser.print_help()
                sys.exit(1)
            dev.mkdir(args[0])
        elif command == "ls":
            parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/")
            parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and  timestamp  (the  modification time, in the local timezone). Times are local.", dest="ll", action="store_true", default=False)
            parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False)
            parser.remove_option("-h")
            parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False)
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            print ls(dev, args[0], recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),
        elif command == "info":
            info(dev)
        elif command == "cp":
            usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\
            "One of source or destination must be a path on the device. \n\nDevice paths have the form\n"+\
            "dev:mountpoint/my/path\n"+\
            "where mountpoint is one of / or card:/\n\n"+\
            "source must point to a file for which you have read permissions\n"+\
            "destination must point to a file or directory for which you have write permissions"
            parser = OptionParser(usage=usage)
            parser.add_option('-f', '--force', dest='force', action='store_true', default=False,
                              help='Overwrite the destination file if it exists already.')
            options, args = parser.parse_args(args)
            if len(args) != 2:
                parser.print_help()
                return 1
            if args[0].startswith("dev:"):
                outfile = args[1]
                path = args[0][7:]
                if path.endswith("/"): path = path[:-1]
                if os.path.isdir(outfile):
                    outfile = os.path.join(outfile, path[path.rfind("/")+1:])
                try:
                    outfile = open(outfile, "wb")
                except IOError as e:
                    print >> sys.stderr, e
                    parser.print_help()
                    return 1
                dev.get_file(path, outfile)
                fsync(outfile)
                outfile.close()
            elif args[1].startswith("dev:"):
                try:
                    infile = open(args[0], "rb")
                except IOError as e:
                    print >> sys.stderr, e
                    parser.print_help()
                    return 1
                try:
                    dev.put_file(infile, args[1][7:])
                except PathError as err:
                    if options.force and 'exists' in str(err):
                        dev.del_file(err.path, False)
                        dev.put_file(infile, args[1][7:])
                    else:
                        raise
                infile.close()
            else:
                parser.print_help()
                return 1
        elif command == "cat":
            outfile = sys.stdout
            parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            if args[0].endswith("/"): path = args[0][:-1]
            else: path = args[0]
            outfile = sys.stdout
            dev.get_file(path, outfile)
        elif command == "rm":
            parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+\
                                  "and must begin with / or card:/\n\n"+\
                                  "rm will DELETE the file. Be very CAREFUL")
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            dev.rm(args[0])
        elif command == "touch":
            parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+
            "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" )
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            dev.touch(args[0])
        elif command == 'test_file':
            parser = OptionParser(usage=("usage: %prog test_file path\n"
                'Open device, copy file specified by path to device and '
                'then eject device.'))
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            path = args[0]
            from calibre.ebooks.metadata.meta import get_metadata
            mi = get_metadata(open(path, 'rb'), path.rpartition('.')[-1].lower())
            print dev.upload_books([args[0]], [os.path.basename(args[0])],
                    end_session=False, metadata=[mi])
            dev.eject()
        else:
            parser.print_help()
            if getattr(dev, 'handle', False): dev.close()
            return 1
    except DeviceLocked:
        print >> sys.stderr, "The device is locked. Use the --unlock option"
    except (ArgumentError, DeviceError) as e:
        print >>sys.stderr, e
        return 1
    finally:
        shutdown_plugins()

    return 0
Esempio n. 43
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, "thumbnail", None)
     if coverdata and coverdata[2]:
         with open("%s.jpg" % os.path.join(path, filename), "wb") as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 44
0
 def upload_cover(self, path, filename, metadata, filepath):
     coverdata = getattr(metadata, 'thumbnail', None)
     if coverdata and coverdata[2]:
         with open('%s.jpg' % os.path.join(path, filename), 'wb') as coverfile:
             coverfile.write(coverdata[2])
             fsync(coverfile)
Esempio n. 45
0
def main():
    from calibre.utils.terminal import geometry
    cols = geometry()[0]

    parser = OptionParser(
        usage="usage: %prog [options] command args\n\ncommand " +
        "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"
        + "For help on a particular command: %prog command",
        version=__appname__ + " version: " + __version__)
    parser.add_option(
        "--log-packets",
        help="print out packet stream to stdout. " +
        "The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
        dest="log_packets",
        action="store_true",
        default=False)
    parser.remove_option("-h")
    parser.disable_interspersed_args()  # Allow unrecognized options
    options, args = parser.parse_args()

    if len(args) < 1:
        parser.print_help()
        return 1

    command = args[0]
    args = args[1:]
    dev = None
    scanner = DeviceScanner()
    scanner.scan()
    connected_devices = []

    for d in device_plugins():
        try:
            d.startup()
        except:
            print('Startup failed for device plugin: %s' % d)
        if d.MANAGES_DEVICE_PRESENCE:
            cd = d.detect_managed_devices(scanner.devices)
            if cd is not None:
                connected_devices.append((cd, d))
                dev = d
                break
            continue
        ok, det = scanner.is_device_connected(d)
        if ok:
            dev = d
            dev.reset(log_packets=options.log_packets, detected_device=det)
            connected_devices.append((det, dev))

    if dev is None:
        print('Unable to find a connected ebook reader.', file=sys.stderr)
        shutdown_plugins()
        return 1

    for det, d in connected_devices:
        try:
            d.open(det, None)
        except:
            continue
        else:
            dev = d
            d.specialize_global_preferences(device_prefs)
            break

    try:
        if command == "df":
            total = dev.total_space(end_session=False)
            free = dev.free_space()
            where = ("Memory", "Card A", "Card B")
            print("Filesystem\tSize \tUsed \tAvail \tUse%")
            for i in range(3):
                print("%-10s\t%s\t%s\t%s\t%s" %
                      (where[i], human_readable(
                          total[i]), human_readable(total[i] - free[i]),
                       human_readable(free[i]),
                       unicode_type(0 if total[i] ==
                                    0 else int(100 * (total[i] - free[i]) /
                                               (total[i] * 1.))) + "%"))
        elif command == 'eject':
            dev.eject()
        elif command == "books":
            print("Books in main memory:")
            for book in dev.books():
                print(book)
            print("\nBooks on storage carda:")
            for book in dev.books(oncard='carda'):
                print(book)
            print("\nBooks on storage cardb:")
            for book in dev.books(oncard='cardb'):
                print(book)
        elif command == "mkdir":
            parser = OptionParser(
                usage=
                "usage: %prog mkdir [options] path\nCreate a folder on the device\n\npath must begin with / or card:/"
            )
            if len(args) != 1:
                parser.print_help()
                sys.exit(1)
            dev.mkdir(args[0])
        elif command == "ls":
            parser = OptionParser(
                usage=
                "usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/"
            )
            parser.add_option(
                "-l",
                help=
                "In addition to the name of each file, print the file type, permissions, and  timestamp  (the  modification time, in the local timezone). Times are local.",  # noqa
                dest="ll",
                action="store_true",
                default=False)
            parser.add_option(
                "-R",
                help=
                "Recursively list subfolders encountered. /dev and /proc are omitted",
                dest="recurse",
                action="store_true",
                default=False)
            parser.remove_option("-h")
            parser.add_option("-h",
                              "--human-readable",
                              help="show sizes in human readable format",
                              dest="hrs",
                              action="store_true",
                              default=False)
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            print(ls(dev,
                     args[0],
                     recurse=options.recurse,
                     ll=options.ll,
                     human_readable_size=options.hrs,
                     cols=cols),
                  end=' ')
        elif command == "info":
            info(dev)
        elif command == "cp":
            usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\
            "One of source or destination must be a path on the device. \n\nDevice paths have the form\n"+\
            "dev:mountpoint/my/path\n"+\
            "where mountpoint is one of / or carda: or cardb:/\n\n"+\
            "source must point to a file for which you have read permissions\n"+\
            "destination must point to a file or folder for which you have write permissions"
            parser = OptionParser(usage=usage)
            parser.add_option(
                '-f',
                '--force',
                dest='force',
                action='store_true',
                default=False,
                help='Overwrite the destination file if it exists already.')
            options, args = parser.parse_args(args)
            if len(args) != 2:
                parser.print_help()
                return 1
            if args[0].startswith("dev:"):
                outfile = args[1]
                path = args[0][4:]
                if path.endswith("/"):
                    path = path[:-1]
                if os.path.isdir(outfile):
                    outfile = os.path.join(outfile, path[path.rfind("/") + 1:])
                try:
                    outfile = lopen(outfile, "wb")
                except IOError as e:
                    print(e, file=sys.stderr)
                    parser.print_help()
                    return 1
                dev.get_file(path, outfile)
                fsync(outfile)
                outfile.close()
            elif args[1].startswith("dev:"):
                try:
                    infile = lopen(args[0], "rb")
                except IOError as e:
                    print(e, file=sys.stderr)
                    parser.print_help()
                    return 1
                dev.put_file(infile, args[1][4:], replace_file=options.force)
                infile.close()
            else:
                parser.print_help()
                return 1
        elif command == "cat":
            outfile = sys.stdout
            parser = OptionParser(
                usage=
                "usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/"
            )
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            if args[0].endswith("/"):
                path = args[0][:-1]
            else:
                path = args[0]
            outfile = sys.stdout
            dev.get_file(path, outfile)
        elif command == "rm":
            parser = OptionParser(
                usage=
                "usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty folder on the device "
                + "and must begin with / or card:/\n\n" +
                "rm will DELETE the file. Be very CAREFUL")
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            dev.rm(args[0])
        elif command == "touch":
            parser = OptionParser(
                usage=
                "usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"
                +  # noqa
                "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing"
            )
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            dev.touch(args[0])
        elif command == 'test_file':
            parser = OptionParser(usage=(
                "usage: %prog test_file path\n"
                'Open device, copy file specified by path to device and '
                'then eject device.'))
            options, args = parser.parse_args(args)
            if len(args) != 1:
                parser.print_help()
                return 1
            path = args[0]
            from calibre.ebooks.metadata.meta import get_metadata
            mi = get_metadata(lopen(path, 'rb'),
                              path.rpartition('.')[-1].lower())
            print(
                dev.upload_books([args[0]], [os.path.basename(args[0])],
                                 end_session=False,
                                 metadata=[mi]))
            dev.eject()
        else:
            parser.print_help()
            if getattr(dev, 'handle', False):
                dev.close()
            return 1
    except DeviceLocked:
        print("The device is locked. Use the --unlock option", file=sys.stderr)
    except (ArgumentError, DeviceError) as e:
        print(e, file=sys.stderr)
        return 1
    finally:
        shutdown_plugins()

    return 0