예제 #1
0
  def utime(self, path, times):
    '''
    Set the times (atime, mtime, and ctime) of a file.

    Returns:
      True upon successful modification, otherwise an errno code is
      returned.
    '''

    self._debug('opcode: utime | path: %s' % (path))

    context = self.GetContext()
    file_stat = tsumufs.getManager(path).statFile(path)

    self._debug('context: %s' % repr(context))
    self._debug('file: uid=%d, gid=%d, mode=%o' %
                (file_stat.st_uid, file_stat.st_gid, file_stat.st_mode))

    # Use 0 values as a workaroud to simulate a change on the fs
    # without updating any document revision.
    if times == (0, 0):
      return 0

    try:
      if tsumufs.getManager(path).utime(path, times):
        tsumufs.syncLog.addMetadataChange(path, times=True)

      return 0
    except OSError, e:
      self._debug('utime: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #2
0
  def access(self, path, mode):
    '''
    Test for access to a path.

    Returns:
      True upon successful check, otherwise an errno code is
      returned.
    '''

    self._debug('opcode: access | path: %s | mode: %o' % (path, mode))

    context = self.GetContext()
    self._debug('uid: %s, gid: %s, pid: %s' %
                (repr(context['uid']),
                 repr(context['gid']),
                 repr(context['pid'])))

    try:
      tsumufs.getManager(path).access(context['uid'], path, mode)

      return 0

    except OSError, e:
      self._debug('access: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #3
0
  def mkdir(self, path, mode):
    '''
    Creates a new directory with the specified mode.

    Returns:
      0 on successful creation, othewrise a negative errno code is returned.
    '''

    self._debug('opcode: mkdir | path: %s | mode: %o' % (path, mode))

    context = self.GetContext()
    parent = os.path.dirname(path)
    tsumufs.getManager(parent).access(context['uid'], parent,
                                      os.W_OK|os.X_OK)

    try:
      if tsumufs.getManager(path).makeDir(path, mode &~ tsumufs.defaultModeMask,
                                          context['uid'], context['gid']):
        tsumufs.syncLog.addNew('dir', filename=path)
      return 0

    except OSError, e:
      self._debug('mkdir: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #4
0
  def unlink(self, path):
    '''
    Callback to unlink a file on disk.

    Returns:
      True on successful unlink, or an errno code on error.
    '''

    self._debug('opcode: unlink | path: %s' % path)

    try:
      context = self.GetContext()
      tsumufs.getManager(os.path.dirname(path)).access(context['uid'],
                                                       os.path.dirname(path),
                                                       os.W_OK)

      if tsumufs.getManager(path).removeCachedFile(path, removeperm=True):
        tsumufs.syncLog.addUnlink(path, 'file')

      return 0

    except OSError, e:
      self._debug('unlink: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #5
0
  def chown(self, path, newuid, newgid):
    '''
    Change the owner and/or group of a file.

    Returns:
      True on successful change, otherwise errno code is returned.
    '''

    self._debug('opcode: chown | path: %s | uid: %d | gid: %d' %
               (path, newuid, newgid))

    context = self.GetContext()
    file_stat = tsumufs.getManager(path).statFile(path)

    if context['uid'] != 0:
      if newuid != -1 and context['uid'] != newuid:
        raise OSError(errno.EPERM, os.strerror(errno.EPERM))

      if (file_stat.st_uid != context['uid']) and (newgid != -1):
        if newgid not in tsumufs.getGidsForUid(context['uid']):
          raise OSError(errno.EPERM, os.strerror(errno.EPERM))

    try:
      if tsumufs.getManager(path).chown(path, newuid, newgid):
        tsumufs.syncLog.addMetadataChange(path, uid=True, gid=True)

      return 0
    except OSError, e:
      self._debug('chown: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #6
0
  def getxattr(self, path, name, size):
    '''
    Callback that is called to get a specific extended attribute size
    or value by name.

    Returns:
      The size of the value (including the null terminator) if size is
        set to 0.
      The string the extended attribute contains if size > 0
      -EOPNOTSUPP if the name is invalid.
    '''
    self._debug('opcode: getxattr | path: %s | name: %s | size: %d'
                % (path, name, size))

    name = name.lower()

    try:
      if name.startswith("security."):
        return -errno.ENODATA

      xattr = tsumufs.getManager(path).getxattr(path, name)

      if size == 0:
        # Caller just wants the size of the value.
        return len(xattr)
      else:
        return xattr

    except OSError, e:
      self._debug('getxattr: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #7
0
  def getattr(self, path):
    '''
    Callback which is called into when a stat() is performed on the
    user side of things.

    Returns:
      A stat result object, the same as an os.lstat() call.

    Raises:
      None
    '''

    self._debug('opcode: getattr (%d) | self: %s | path: %s'
                % (self.GetContext()['pid'], repr(self), path))

    try:
      result = tsumufs.getManager(path).statFile(path)

      self._debug('Returning (%d, %d, %o)' %
                  (result.st_uid, result.st_gid, result.st_mode))

      return result

    except OSError, e:
      self._debug('getattr: Caught OSError: %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #8
0
  def removexattr(self, path, name):
    '''
    Callback that is called into when a setxattr() call is
    performed. This removes an extended attribute, if that
    attribute is non-readonly. If the attribute isn't a valid name, or
    is read-only, this method returns -errno.EOPNOTSUPP.

    Returns:
      None, or -EOPNOTSUPP on error.
    '''

    self._debug('opcode: removexattr | path: %s | name: %s' % (path, name))

    mode = tsumufs.getManager(path).statFile(path).st_mode

    if path == '/':
      type_ = 'root'
    elif stat.S_ISDIR(mode):
      type_ = 'dir'
    else:
      type_ = 'file'

    try:
      return tsumufs.ExtendedAttributes.removeXAttr(type_, path, name)
    except KeyError, e:
      self._debug('Request for extended attribute that is not present in the '
                  'dictionary: <%s, %s, %s>'
                  % (repr(type_), repr(path), repr(name)))
예제 #9
0
  def rename(self, old, new):
    '''
    Renames a file from old to new, possibly changing it's path as
    well as its filename.

    Returns:
      True on successful rename, or errno code on error.
    '''

    self._debug('opcode: rename | old: %s | new: %s' % (old, new))

    try:
      context = self.GetContext()

      # According to the rename(2) man page, EACCES is raised when:
      #
      #   Write permission is denied for the directory containing oldpath or
      #   newpath, or, search permission is denied for one of the directories in
      #   the path prefix of oldpath or newpath, or oldpath is a directory and
      #   does not allow write permission (needed to update the ..  entry).
      #
      # Otherwise the rename is allowed. It doesn't care about permissions on
      # the file itself.

      # So, do this:
      #  1. Stat old. If dir and not W_OK, EACCES
      #  2. Verify X_OK | W_OK on dirname(old) and dirname(new)

      old_stat = tsumufs.getManager(old).statFile(old)

      if stat.S_ISDIR(old_stat.st_mode):
        tsumufs.getManager(old).access(context['uid'], old, os.W_OK)

      tsumufs.getManager(os.path.dirname(old)).access(context['uid'],
                                                   os.path.dirname(old),
                                                   os.X_OK | os.W_OK)
      tsumufs.getManager(os.path.dirname(new)).access(context['uid'],
                                                   os.path.dirname(new),
                                                   os.X_OK | os.W_OK)

      # Restore the real file path if old has been acceded via
      # a view virtual folder.
      if tsumufs.viewsManager.isAnyViewPath(old):
        old = tsumufs.viewsManager.realFilePath(old)

      if tsumufs.getManager(new).rename(old, new):
        tsumufs.syncLog.addRename(old, new)

      return 0

    except OSError, e:
      self._debug('rename: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #10
0
  def rmdir(self, path):
    '''
    Removes a directory from disk.

    Returns:
      True on successful unlink, or errno code on error.
    '''

    self._debug('opcode: rmdir | path: %s' % path)

    try:
      context = self.GetContext()
      tsumufs.getManager(path).access(context['uid'], path, os.W_OK)

      if tsumufs.getManager(path).removeCachedFile(path, removeperm=True):
        tsumufs.syncLog.addUnlink(path, 'dir')

      return 0
    except OSError, e:
      self._debug('rmdir: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #11
0
  def mknod(self, path, mode, dev):
    '''
    Creates a special device file with the specified mode and device
    number.

    Returns:
      True on successful creation, otherwise an errno code is
      returned.
    '''

    self._debug('opcode: mknod | path: %s | mode: %d | dev: %s' %
               (path, mode, dev))

    context = self.GetContext()

    if mode & (stat.S_IFCHR | stat.S_IFBLK):
      if context['uid'] != 0:
        raise OSError(errno.EPERM)

    parent = os.path.dirname(path)
    tsumufs.getManager(parent).access(context['uid'], parent, os.W_OK|os.X_OK)

    try:
      if tsumufs.getManager(path).makeNode(path, mode &~ tsumufs.defaultModeMask, dev):

        if mode & stat.S_IFREG:
          tsumufs.syncLog.addNew('file', filename=path)
        elif mode & stat.S_IFCHR:
          tsumufs.syncLog.addNew('dev', filename=path, dev_type='char')
        elif mode & stat.S_IFBLK:
          tsumufs.syncLog.addNew('dev', filename=path, dev_type='block')
        elif mode & stat.S_IFIFO:
          tsumufs.syncLog.addNew('fifo', filename=path)

      return 0
    except OSError, e:
      self._debug('mknod: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #12
0
  def symlink(self, src, dest):
    '''
    Creates a symlink pointing to src as a file called dest.

    Returns:
      True on successful link creation, or errno code on error.
    '''

    self._debug('opcode: symlink | src: %s | dest: %s' % (src, dest))

    try:
      context = self.GetContext()
      parent = os.path.dirname(dest)
      tsumufs.getManager(parent).access(context['uid'], parent, os.W_OK | os.X_OK)

      if tsumufs.getManager(dest).makeSymlink(src, dest, context['uid'], context['gid']):
        tsumufs.syncLog.addNew('symlink', filename=dest)

      return 0
    except OSError, e:
      self._debug('symlink: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #13
0
  def readlink(self, path):
    '''
    Reads the value of a symlink.

    Returns:
      The string representation of the file the symlink points to, or
      a negative errno code on error.
    '''

    self._debug('opcode: readlink | path: %s' % path)

    try:
      context = self.GetContext()
      tsumufs.getManager(path).access(context['uid'], path, os.R_OK)

      retval = tsumufs.getManager(path).readLink(path)

      self._debug('Returning: %s' % retval)
      return retval
    except OSError, e:
      self._debug('readlink: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #14
0
  def opendir(self, path):
    '''
    Test for access to a directory path.

    Returns:
      True upon successful check, otherwise an errno code is
      returned.
    '''

    self._debug('opcode: opendir | path: %s' % path)

    context = self.GetContext()
    self._debug('uid: %s, gid: %s, pid: %s' %
                (repr(context['uid']),
                 repr(context['gid']),
                 repr(context['pid'])))

    try:
      tsumufs.getManager(path).access(context['uid'], path, os.R_OK | os.X_OK)
      return 0
    except OSError, e:
      self._debug('opendir: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #15
0
  def chmod(self, path, mode):
    '''
    Changes the mode of a file.

    Returns:
      True on successful mode change, or errno code on error.
    '''

    self._debug('opcode: chmod | path: %s | mode: %o' % (path, mode))

    context = self.GetContext()
    file_stat = tsumufs.getManager(path).statFile(path)

    self._debug('context: %s' % repr(context))
    self._debug('file: uid=%d, gid=%d, mode=%o' %
                (file_stat.st_uid, file_stat.st_gid, file_stat.st_mode))

    if ((file_stat.st_uid != context['uid']) and
        (context['uid'] != 0)):
      self._debug('chmod: user not owner, and user not root -- EPERM')
      return -errno.EPERM

    tsumufs.getManager(path).access(context['uid'],
                                    os.path.dirname(path),
                                    os.F_OK)

    try:
      self._debug('chmod: access granted -- chmoding')
      if tsumufs.getManager(path).chmod(path, mode &~ tsumufs.defaultModeMask):
        tsumufs.syncLog.addMetadataChange(path, mode=True)

      return 0
    except OSError, e:
      self._debug('chmod: Caught OSError: errno %d: %s'
                  % (e.errno, e.strerror))
      return -e.errno
예제 #16
0
  def listxattr(self, path, size):
    '''
    Callback method to list the names of valid extended attributes in
    a file.

    Returns:
      The number of variables available if size is 0.
      A list of key names if size > 0.
    '''

    self._debug('opcode: listxattr | path: %s | size: %d'
                % (path, size))

    keys = tsumufs.getManager(path).listxattr(path)

    if size == 0:
      return len(''.join(keys)) + len(keys)

    return keys
예제 #17
0
  def readdir(self, path, offset):
    '''
    Generator callback that returns a fuse.Direntry object every time
    it is called. Similar to the C readdir() call.

    Returns:
      A generator that yields a fuse.Direntry object, or an errno
      code on error.
    '''

    self._debug('opcode: readdir | path: %s | offset: %d' % (path, offset))

    try:
      for filename in [ '.', '..' ]:
        dirent = fuse.Direntry(filename)
        dirent.type = stat.S_IFDIR
        dirent.offset = offset

        yield dirent

      dociterators = [ tsumufs.getManager(path).getDirents(path) ]

      if path == tsumufs.viewsPoint:
        # Append the root directories of views
        dociterators.append(tsumufs.viewsManager.getRootDirs())

      for dociterator in dociterators:
        for doc in dociterator:
          dirent        = fuse.Direntry(str(doc.filename))
          dirent.type   = stat.S_IFMT(doc.mode)
          dirent.offset = offset

          yield dirent

    except OSError, e:
      self._debug('readdir: Caught OSError on %s: errno %d: %s'
                  % (filename, e.errno, e.strerror))

      yield -e.errno
예제 #18
0
    elif stat.S_ISDIR(mode):
      type_ = 'dir'
    else:
      type_ = 'file'

    try:
      return tsumufs.ExtendedAttributes.setXAttr(type_, path, name, value)
    except KeyError, e:
      self._debug('Request for extended attribute that is not present in the '
                  'dictionary: <%s, %s, %s>'
                  % (repr(type_), repr(path), repr(name)))

    try:
      context = self.GetContext()

      tsumufs.getManager(path).access(context['uid'], path, os.W_OK)

      if tsumufs.getManager(path).setxattr(path, name, value):
        tsumufs.syncLog.addMetadataChange(path, xattrs=[name], acls=(name == "system.posix_acl_access"))

      return 0

    except Exception, e:
      return -errno.EOPNOTSUPP

  @benchmark
  def removexattr(self, path, name):
    '''
    Callback that is called into when a setxattr() call is
    performed. This removes an extended attribute, if that
    attribute is non-readonly. If the attribute isn't a valid name, or
예제 #19
0
      def __new__(cls, path, *args, **kwargs):
        kwargs.update(self.GetContext())

        klass = tsumufs.getManager(path).getFileClass(path) or tsumufs.FuseFile

        return klass(path, *args, **kwargs)