Skip to content
This repository has been archived by the owner on Mar 4, 2021. It is now read-only.

Commit

Permalink
Merge commit 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jyrki Pulliainen committed Jul 4, 2009
2 parents c2ed55c + 6beb241 commit f8deaf1
Show file tree
Hide file tree
Showing 12 changed files with 371 additions and 157 deletions.
1 change: 1 addition & 0 deletions filesystem/__init__.py
Expand Up @@ -11,5 +11,6 @@
StatWrappersMixin,
InsecurePathError,
CrossDeviceRenameError,
raise_on_insecure_file_name
)

30 changes: 20 additions & 10 deletions filesystem/_base.py
Expand Up @@ -24,6 +24,18 @@ class CrossDeviceRenameError(Exception):
"""
pass

## utility function for checking for safe file names.
## TODO: should it be encapsulated within a class?
def raise_on_insecure_file_name(name):
if u'/' in name:
raise InsecurePathError(
'child name contains directory separator')
# this may be too naive
if name == u'..':
raise InsecurePathError(
'child trying to climb out of directory')



## TODO: RFC: Is there any presedence for this naming convention? As
## I understand it, "Mixin" means that this class can be mixed into
Expand All @@ -34,7 +46,10 @@ class StatWrappersMixin(object):
"""
If a class implements stat(), several other methods can be
implemented as wrappers around stat. Simply pull in this class to
get those implemented: exists, isdir, isfile, islink, size.
get those implemented: exists, isdir, isfile, islink, size. (islink
depends on lstat being implemented - assumes the file system does
not support symlinks and hence has no symlinks if lstat is not
implemented)
"""
def size(self):
"""
Expand Down Expand Up @@ -88,7 +103,8 @@ def islink(self):
Raise an ``OSError`` if the operation fails.
"""
return stat.S_ISLNK(self.stat().st_mode)
return (hasattr(self, 'lstat') and
stat.S_ISLNK(self.lstat().st_mode))


class WalkMixin(object):
Expand Down Expand Up @@ -128,7 +144,7 @@ def walk(self, topdown=True):
for d in subdirs:
if (d.parent() != self or d == self):
raise InsecurePathError("walk is only allowed into subdirs")
if not d.islink():
if not (hasattr(d, 'islink') and d.islink()):
for w in d.walk(topdown):
yield w
if not topdown:
Expand Down Expand Up @@ -203,13 +219,7 @@ def child(self, *segments):
"""
p = self
for segment in segments:
if u'/' in segment:
raise InsecurePathError(
'child name contains directory separator')
# this may be too naive
if segment == u'..':
raise InsecurePathError(
'child trying to climb out of directory')
raise_on_insecure_file_name(segment)
p = p.join(segment)
return p

Expand Down
37 changes: 37 additions & 0 deletions filesystem/_localfs.py
@@ -1,5 +1,8 @@
import errno
import os
import stat
import pwd
import grp

from filesystem._base import (
PathnameMixin,
Expand Down Expand Up @@ -62,6 +65,19 @@ def stat(self):
"""
return os.stat(self._pathname)

def lstat(self):
return os.lstat(self._pathname)

def symlink(self, target):
"""
let self be symlinked to target (RFC: the direction of symlink
is not completely intuitive - maybe we should rename it to
symlink_to and/or symlink_from?)
"""
if not hasattr(target, 'root') or self.root != target.root:
raise OSError(errno=errno.EXDEV)
os.symlink(self._pathname, target._pathname)

def readlink(self):
"""
Return the ``path`` as a string to which the link represented
Expand All @@ -72,8 +88,29 @@ def readlink(self):
"""
# TODO: do we care about ``os.readlink`` returning a string or
# unicode string?
## TODO: shouldn't we return a path object instead?
return os.readlink(self._pathname)

def _chown(self, new_user, new_group, chown_method):
## RFC: I think we should have this "batteries included" logics,
## or it will be quite hard to use chown - but this should
## probably be moved to a helper class.
if new_group is None:
new_group = self.stat().st_gid
if new_user is None:
new_user = self.stat().st_uid
if not isinstance(new_user, int):
new_user = pwd.getpwnam(new_user).pw_uid
if not isinstance(new_group, int):
new_group = grp.getgrnam(new_group).gr_gid
chown_method(self._pathname, new_user, new_group)

def chown(self, new_user=None, new_group=None):
return self._chown(new_user, new_group, os.chown)

def lchown(self, new_user=None, new_group=None):
return self._chown(new_user, new_group, os.lchown)

def unlink(self):
"""
Remove the file or link identified by this path.
Expand Down
1 change: 1 addition & 0 deletions filesystem/inmem.py
Expand Up @@ -134,6 +134,7 @@ def child(self, segment=None, *segments):
return self

if not self._children.has_key(segment):
filesystem.raise_on_insecure_file_name(segment)
child = self.__class__(name=segment, parent=self)
self._children[segment] = child

Expand Down
72 changes: 0 additions & 72 deletions filesystem/pep.rst

This file was deleted.

0 comments on commit f8deaf1

Please sign in to comment.