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
def access(self, uid, fusepath, mode): ''' Test for access to a path. Returns: True upon successful check, otherwise False. Don't alter _recurse. That's used internally. Raises: OSError upon access problems. ''' self.lockFile(fusepath) try: opcodes = self._genCacheOpcodes(fusepath) self._validateCache(fusepath, opcodes) realpath = self._generatePath(fusepath, opcodes) if 'use-nfs' in opcodes: logger.debug('Using nfs for access') return os.access(realpath, mode) # TODO(cleanup): make the above chunk of code into a decorator for crying # out loud. We do this in every public method and it adds confusion. =o( # Root owns everything if uid == 0: logger.debug('Root -- returning 0') return 0 # Recursively go down the path from longest to shortest, checking access # perms on each directory as we go down. if fusepath != '/': self.access(uid, os.path.dirname(fusepath), os.X_OK) file_stat = self.statFile(fusepath) mode_string = '' if mode & os.R_OK: mode_string += 'R_OK|' if mode & os.W_OK: mode_string += 'W_OK|' if mode & os.X_OK: mode_string += 'X_OK|' if mode == os.F_OK: mode_string = 'F_OK|' mode_string = mode_string[:-1] logger.debug('access(%s, %s) -> (uid, gid, mode) = (%d, %d, %o)' % (repr(fusepath), mode_string, file_stat.st_uid, file_stat.st_gid, file_stat.st_mode)) # Catch the case where the user only wants to check if the file exists. if mode == os.F_OK: logger.debug('User just wanted to verify %s existed -- returning 0.' % fusepath) return 0 # Check user bits first if uid == file_stat.st_uid: if ((file_stat.st_mode & stat.S_IRWXU) >> 6) & mode: logger.debug('Allowing for user bits.') return 0 # Then group bits if file_stat.st_gid in tsumufs.getGidsForUid(uid): if ((file_stat.st_mode & stat.S_IRWXG) >> 3) & mode: logger.debug('Allowing for group bits.') return 0 # Finally assume other bits if (file_stat.st_mode & stat.S_IRWXO) & mode: logger.debug('Allowing for other bits.') return 0 logger.debug('No access allowed.') raise OSError(errno.EACCES, os.strerror(errno.EACCES)) finally: self.unlockFile(fusepath)