1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 54 55 56 64 66 72 73 75 78 79 90 91 93 94 97 98 101 102 107 108 113 114 116 117 118 119 122 123 125 126 127 128 130 131 133 134 135 136 137 138 139 142 143 144 147 151 152 155 156 157 162 165 166 167 168 170 171 172 174 176 177 179 180 182 183 185 186 188 189 191 192 194 195 197 198 200 201 203 204 205 206 207 208 210 211 213 214 215 217 219 220 222 223 225 226 228 229 230 232 234 235 237 239 240 245 246 249 250 252 257 260 263 264 265 266 267 268 271 273 274 277 279 280 283 288 290 295 297 302 305 307 308 311 313 317 319 321 325 326 328 331 334 336 337 339 341 344 345 353 354 357 360 362 363 365 369 374 377 379 380 381 382 388 395 402 405 406 408 411 412 414 420 422 425 426 434 435 437 440 441 443 444 446 449 450 452 453 455 460 461 468 470 471 472 473 474 475 476 477 478 479 480 481 484 487 489 490 491 492 493 494 495 496 497 498 499 500 501 502 504 507 508 512 515 516 519 521 523 524 525 526 527 528 529 530 531 532 533 534 535 536 538 539 540 541 542 543 544 545 546 547 548 549 551 552 554 557 559 560 562 563 565 567 568 570 571 572 574 575 577 579 584 587 600 603 607 613 614 616 623 630 632 633 634 637 644 645 648 654 655 657 660 661 662 663 664 665 666 668 669 670 672 673 675 679 680 681 682 686 688 691 704 705 708 709 710 712 714 715 716 724 725 727 730 731 733 734 736 737 740 743 745 746 748 749 750 751 752 753 754 756 758 760 761 762 764 765 766 767 768 769 770 771 772 773 775 776 777 778 779 780 781 783 784 786 787 788 789 790 791 792 793 794 795 797 798 799 802 803 804 805 806 807 808 809 810 811 812 813 814 818 819 821 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 866 867 868 869 871 872 873 874 875 876 877 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 925 |
# -*- test-case-name: bloggerfs.tests.test_bloggerfs -*-
# bloggerfs.py - blogger file system in userspace using FUSE # Copyright (C) 2010 Marco Giusti # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; if not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA
# rfc3339.py -- Implementation of the majority of RFC 3339 for python. # Copyright (c) 2008, 2009, 2010 LShift Ltd. <query@lshift.net>
# gdata - Python client library for Google data APIs # Copyright (C) 2009 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.
except: import StringIO as StringIO
"""Return all members of an object as (name, value) pairs sorted by name. Optionally, only return members that satisfy a given predicate.""" else: mro = (obj,) # First try to get the value via __dict__. Some descriptors don't # like calling their __get__ (see bug #1785). else: value = getattr(obj, key)
# Taken from Twisted
""" Return the adapter factory for the given parameters in the given registry, or None if there is not one. """
"""Register an adapter class.
An adapter class is expected to implement the given interface, by adapting instances implementing 'origInterface'. An adapter class's __init__ method should accept one parameter, an instance implementing 'origInterface'. """ global ALLOW_DUPLICATES
# deal with class->interface adapters:
raise ValueError("an adapter (%s) was already registered." % (factory, ))
# add global adapter lookup hook for our newly created registry else:
# End taken
""""""
"""File open operation"""
""""""
""""""
""""""
""""""
""""""
""""""
""""""
""""""
"""Get file attributes.
Similar to stat(). The 'st_dev' and 'st_blksize' fields are ignored. The 'st_ino' field is ignored except if the 'use_ino' mount option is given."""
""""""
""""""
""""""
""""""
""""""
""""""
self.type != other.type or self.ino != other.ino:
def __repr__(self): type = self.type == stat.S_IFREG and 'file' or 'dir' return '<bloggerfs.DirEntry name="%s", type="%s">' % (self.name, type)
def mtime(self):
def ctime(self):
def text(self):
st_uid=os.getuid(), st_gid=os.getgid(), st_size=size, st_ctime=self.ctime, st_mtime=self.mtime)
def text(self): return ''
return {}
def children(self):
if k not in self.children: raise IOError(errno.ENOENT, 'No such file or directory') del self.children[k]
st_uid=os.geteuid(), st_gid=os.getegid(), st_size=4096, st_ctime=self.ctime, st_mtime=self.mtime)
def children(self): shouldUpdate = False else:
for i, el in enumerate(self.original))
for k, v in self.original.iteritems())
continue
# class LabelNode(ElementNode):
# def rmdir(self): # post = self.getParent(IPost, self.parent) # if post is not None: # post.deleteLabel(self) # return 0 # raise IOError(errno.EACCES, 'Permission denied')
def updated(self): if self._updated is None: if self.original.updated: try: updated = self.original.updated.text updated = rfc3339.parse_datetime(updated) self._updated = int(time.mktime(updated.timetuple())) except: _exception('') self._updated = int(time.time()) else: self._updated = int(time.time()) return self._updated
def children(self): self.stale = False self._children = None
def published(self): if self._published is None: if self.original.published: try: published = self.original.published.text published = rfc3339.parse_datetime(published) self._published = int(time.mktime(published.timetuple())) except: _exception('') self._published = self.mtime else: self._published = self.mtime return self._published
o = self.original try: newo = self.client.get_entry(o.get_self_link().href, etag=o.etag, desired_class=o.__class__) self.original = newo if self.stale: self.stale = False except gdata.client.NotModified: pass except gdata.client.RequestError: _exception('')
return self.original.get_blog_name()
return self.original.get_comment_id()
self.client.delete(self.original) self.parent.deleteChild(self.getCommentId())
all_lbls.append(lbl.term) raise IOError(errno.EMSGSIZE, 'The combined length of ' 'all the labels must be at most 200 ' 'characters')
_self._sio.getvalue(), body_type=_type)
except gdata.client.RequestError: _exception('')
# def deleteLabel(self, labelNode): # if 'category' in self.children: # cat = self.getChild('category') # if not self.dirty: # self.dirty = True
self.client.delete(self.original) self.parent.deleteChild(self.getPostId())
def getEntry(feed): if len(feed.entry) > 0: return feed.entry[0]
def getEntry(entry):
self.parent.getBlogId(), desired_class=gdata.blogger.data.BlogPost) raise IOError(errno.EINVAL, 'Cannot parse xml to a valid class')
def id(self): return self.original.get_blog_id()
except gdata.client.RequestError: _exception('')
self.buildChildNode(post))
_warn('Not implemented yet')
self.client = client
if self._original is None: try: self._original = self.client.get_blogs() except gdata.client.RequestError, e: _exception('') raise IOError(errno.EIO, e.reason) return self._original self._original = val
def parent(self): return self
return dict((e.get_blog_id(), self.buildChildNode(e)) for e in self.original.entry)
# def update(self): # try: # self._original = client.get_blogs() # except gdata.client.RequestError, e: # _exception('') # raise IOError(errno.EIO, e.reason)
_warn('Not implemented yet')
# def getParent(self, iface): # if iface.providedBy(self): # return self # return None
@functools.wraps def wrapper(*args, **kwds): try: return f(*args, **kwds) except: _exception('Error in fuse api') raise return wrapper
return (path.split('/')[1:], [])[path == '/']
try: parts = splitpath(path) node = self.account.locate(parts) # if node.stale: # node.update() func = getattr(node, name, None) if func is None: raise IOError(errno.ENOSYS, 'Function %s not ' 'implemented' % name) return func(*args, **kwds) except: _exception('Error in %s' % name) raise
if self.parser.fuse_args.mount_expected(): options = self.cmdline[0] if options.debug: _logger.setLevel(logging.DEBUG) if options.syslog: from logging import handlers handler = handlers.SysLogHandler() elif options.logfile: from logging import handlers handler = handlers.FileHandler(options.logfile) elif options.debug: handler = logging.StreamHandler() formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] ' '[%(funcName)s] %(message)s') handler.setFormatter(formatter) _logger.addHandler(handler)
client = gdata.blogger.client.BloggerClient() self.account = AccountNode(client)
if not options.email: from gdata.sample_util import authorize_client authorize_client(client, service='blogger', source='bloggerfs', scopes=['http://www.blogger.com/feeds/']) else: email = options.email if not options.password: import getpass password = getpass.getpass() else: password = options.password client.client_login(email, password, source='bloggerfs', service='blogger') fuse.Fuse.main(self)
# files # rename = callNodeMethod('rename') # fsync = callNodeMethod('fsync')
# directories # rmdir = callNodeMethod('rmdir') # mkdir = callNodeMethod('mkdir') # opendir = callNodeMethod('opendir') # releasedir = callNodeMethod('releasedir') # fsyncdir = callNodeMethod('fsyncdir')
# misc # setattr = callNodeMethod('setattr') # setxattr = callNodeMethod('setxattr') # fgetattr = callNodeMethod('fgetattr') # getxattr = callNodeMethod('getxattr') # listxattr = callNodeMethod('listxattr') # setxattr = callNodeMethod('setxattr') # removexattr = callNodeMethod('removexattr') # statfs = callNodeMethod('statfs') # utime = callNodeMethod('utime') # utimens = callNodeMethod('utimens') # mknod = callNodeMethod('mknod') # chmod = callNodeMethod('chmod') # chown = callNodeMethod('chown') # create = callNodeMethod('create') # ftruncate = callNodeMethod('ftruncate') # access = callNodeMethod('access') # lock = callNodeMethod('lock') # utimens = callNodeMethod('utimens') # bmap = callNodeMethod('bmap')
# links # readlink = callNodeMethod('readlink') # unlink = callNodeMethod('unlink') # symlink = callNodeMethod('symlink') # link = callNodeMethod('link')
if argv is None: import sys argv = sys.argv[1:]
server = BloggerFS() server.parser.add_option('-e', '--email', help='Google account email') server.parser.add_option('-p', '--password', help='Google account password') server.parser.add_option('-b', '--debug', help='Show debugging info', action='store_true') server.parser.add_option('--syslog', action='store_true', help='Log messages to syslog') server.parser.add_option('-l', '--logfile', help='Log messages to file') server.parse(args=argv, errex=1) server.main()
main() |