+++ /dev/null
-"""File System Proxy.\r
-\r
-Provide an OS-neutral view on a file system, locally or remotely.\r
-The functionality is geared towards implementing some sort of\r
-rdist-like utility between a Mac and a UNIX system.\r
-\r
-The module defines three classes:\r
-\r
-FSProxyLocal -- used for local access\r
-FSProxyServer -- used on the server side of remote access\r
-FSProxyClient -- used on the client side of remote access\r
-\r
-The remote classes are instantiated with an IP address and an optional\r
-verbosity flag.\r
-"""\r
-\r
-import server\r
-import client\r
-import md5\r
-import os\r
-import fnmatch\r
-from stat import *\r
-import time\r
-import fnmatch\r
-\r
-maxnamelen = 255\r
-\r
-skipnames = (os.curdir, os.pardir)\r
-\r
-\r
-class FSProxyLocal:\r
-\r
- def __init__(self):\r
- self._dirstack = []\r
- self._ignore = ['*.pyc'] + self._readignore()\r
-\r
- def _close(self):\r
- while self._dirstack:\r
- self.back()\r
-\r
- def _readignore(self):\r
- file = self._hide('ignore')\r
- try:\r
- f = open(file)\r
- except IOError:\r
- file = self._hide('synctree.ignorefiles')\r
- try:\r
- f = open(file)\r
- except IOError:\r
- return []\r
- ignore = []\r
- while 1:\r
- line = f.readline()\r
- if not line: break\r
- if line[-1] == '\n': line = line[:-1]\r
- ignore.append(line)\r
- f.close()\r
- return ignore\r
-\r
- def _hidden(self, name):\r
- return name[0] == '.'\r
-\r
- def _hide(self, name):\r
- return '.%s' % name\r
-\r
- def visible(self, name):\r
- if len(name) > maxnamelen: return 0\r
- if name[-1] == '~': return 0\r
- if name in skipnames: return 0\r
- if self._hidden(name): return 0\r
- head, tail = os.path.split(name)\r
- if head or not tail: return 0\r
- if os.path.islink(name): return 0\r
- if '\0' in open(name, 'rb').read(512): return 0\r
- for ign in self._ignore:\r
- if fnmatch.fnmatch(name, ign): return 0\r
- return 1\r
-\r
- def check(self, name):\r
- if not self.visible(name):\r
- raise os.error, "protected name %s" % repr(name)\r
-\r
- def checkfile(self, name):\r
- self.check(name)\r
- if not os.path.isfile(name):\r
- raise os.error, "not a plain file %s" % repr(name)\r
-\r
- def pwd(self):\r
- return os.getcwd()\r
-\r
- def cd(self, name):\r
- self.check(name)\r
- save = os.getcwd(), self._ignore\r
- os.chdir(name)\r
- self._dirstack.append(save)\r
- self._ignore = self._ignore + self._readignore()\r
-\r
- def back(self):\r
- if not self._dirstack:\r
- raise os.error, "empty directory stack"\r
- dir, ignore = self._dirstack[-1]\r
- os.chdir(dir)\r
- del self._dirstack[-1]\r
- self._ignore = ignore\r
-\r
- def _filter(self, files, pat = None):\r
- if pat:\r
- def keep(name, pat = pat):\r
- return fnmatch.fnmatch(name, pat)\r
- files = filter(keep, files)\r
- files = filter(self.visible, files)\r
- files.sort()\r
- return files\r
-\r
- def list(self, pat = None):\r
- files = os.listdir(os.curdir)\r
- return self._filter(files, pat)\r
-\r
- def listfiles(self, pat = None):\r
- files = os.listdir(os.curdir)\r
- files = filter(os.path.isfile, files)\r
- return self._filter(files, pat)\r
-\r
- def listsubdirs(self, pat = None):\r
- files = os.listdir(os.curdir)\r
- files = filter(os.path.isdir, files)\r
- return self._filter(files, pat)\r
-\r
- def exists(self, name):\r
- return self.visible(name) and os.path.exists(name)\r
-\r
- def isdir(self, name):\r
- return self.visible(name) and os.path.isdir(name)\r
-\r
- def islink(self, name):\r
- return self.visible(name) and os.path.islink(name)\r
-\r
- def isfile(self, name):\r
- return self.visible(name) and os.path.isfile(name)\r
-\r
- def sum(self, name):\r
- self.checkfile(name)\r
- BUFFERSIZE = 1024*8\r
- f = open(name)\r
- sum = md5.new()\r
- while 1:\r
- buffer = f.read(BUFFERSIZE)\r
- if not buffer:\r
- break\r
- sum.update(buffer)\r
- return sum.digest()\r
-\r
- def size(self, name):\r
- self.checkfile(name)\r
- return os.stat(name)[ST_SIZE]\r
-\r
- def mtime(self, name):\r
- self.checkfile(name)\r
- return time.localtime(os.stat(name)[ST_MTIME])\r
-\r
- def stat(self, name):\r
- self.checkfile(name)\r
- size = os.stat(name)[ST_SIZE]\r
- mtime = time.localtime(os.stat(name)[ST_MTIME])\r
- return size, mtime\r
-\r
- def info(self, name):\r
- sum = self.sum(name)\r
- size = os.stat(name)[ST_SIZE]\r
- mtime = time.localtime(os.stat(name)[ST_MTIME])\r
- return sum, size, mtime\r
-\r
- def _list(self, function, list):\r
- if list is None:\r
- list = self.listfiles()\r
- res = []\r
- for name in list:\r
- try:\r
- res.append((name, function(name)))\r
- except (os.error, IOError):\r
- res.append((name, None))\r
- return res\r
-\r
- def sumlist(self, list = None):\r
- return self._list(self.sum, list)\r
-\r
- def statlist(self, list = None):\r
- return self._list(self.stat, list)\r
-\r
- def mtimelist(self, list = None):\r
- return self._list(self.mtime, list)\r
-\r
- def sizelist(self, list = None):\r
- return self._list(self.size, list)\r
-\r
- def infolist(self, list = None):\r
- return self._list(self.info, list)\r
-\r
- def _dict(self, function, list):\r
- if list is None:\r
- list = self.listfiles()\r
- dict = {}\r
- for name in list:\r
- try:\r
- dict[name] = function(name)\r
- except (os.error, IOError):\r
- pass\r
- return dict\r
-\r
- def sumdict(self, list = None):\r
- return self.dict(self.sum, list)\r
-\r
- def sizedict(self, list = None):\r
- return self.dict(self.size, list)\r
-\r
- def mtimedict(self, list = None):\r
- return self.dict(self.mtime, list)\r
-\r
- def statdict(self, list = None):\r
- return self.dict(self.stat, list)\r
-\r
- def infodict(self, list = None):\r
- return self._dict(self.info, list)\r
-\r
- def read(self, name, offset = 0, length = -1):\r
- self.checkfile(name)\r
- f = open(name)\r
- f.seek(offset)\r
- if length == 0:\r
- data = ''\r
- elif length < 0:\r
- data = f.read()\r
- else:\r
- data = f.read(length)\r
- f.close()\r
- return data\r
-\r
- def create(self, name):\r
- self.check(name)\r
- if os.path.exists(name):\r
- self.checkfile(name)\r
- bname = name + '~'\r
- try:\r
- os.unlink(bname)\r
- except os.error:\r
- pass\r
- os.rename(name, bname)\r
- f = open(name, 'w')\r
- f.close()\r
-\r
- def write(self, name, data, offset = 0):\r
- self.checkfile(name)\r
- f = open(name, 'r+')\r
- f.seek(offset)\r
- f.write(data)\r
- f.close()\r
-\r
- def mkdir(self, name):\r
- self.check(name)\r
- os.mkdir(name, 0777)\r
-\r
- def rmdir(self, name):\r
- self.check(name)\r
- os.rmdir(name)\r
-\r
-\r
-class FSProxyServer(FSProxyLocal, server.Server):\r
-\r
- def __init__(self, address, verbose = server.VERBOSE):\r
- FSProxyLocal.__init__(self)\r
- server.Server.__init__(self, address, verbose)\r
-\r
- def _close(self):\r
- server.Server._close(self)\r
- FSProxyLocal._close(self)\r
-\r
- def _serve(self):\r
- server.Server._serve(self)\r
- # Retreat into start directory\r
- while self._dirstack: self.back()\r
-\r
-\r
-class FSProxyClient(client.Client):\r
-\r
- def __init__(self, address, verbose = client.VERBOSE):\r
- client.Client.__init__(self, address, verbose)\r
-\r
-\r
-def test():\r
- import string\r
- import sys\r
- if sys.argv[1:]:\r
- port = string.atoi(sys.argv[1])\r
- else:\r
- port = 4127\r
- proxy = FSProxyServer(('', port))\r
- proxy._serverloop()\r
-\r
-\r
-if __name__ == '__main__':\r
- test()\r