# Copyright 2013 Dean Gardiner # # 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. from asio.file import File, DEFAULT_BUFFER_SIZE from asio.interfaces.base import Interface import sys import os if os.name == 'posix': import select # fcntl is only required on darwin if sys.platform == 'darwin': import fcntl F_GETPATH = 50 class PosixInterface(Interface): @classmethod def open(cls, file_path, parameters=None): """ :type file_path: str :rtype: asio.interfaces.posix.PosixFile """ if not parameters: parameters = {} if not parameters.get('mode'): parameters.pop('mode') if not parameters.get('buffering'): parameters.pop('buffering') fd = os.open(file_path, os.O_RDONLY | os.O_NONBLOCK) return PosixFile(fd) @classmethod def get_size(cls, fp): """ :type fp: asio.interfaces.posix.PosixFile :rtype: int """ return os.fstat(fp.fd).st_size @classmethod def get_path(cls, fp): """ :type fp: asio.interfaces.posix.PosixFile :rtype: int """ # readlink /dev/fd fails on darwin, so instead use fcntl F_GETPATH if sys.platform == 'darwin': return fcntl.fcntl(fp.fd, F_GETPATH, '\0' * 1024).rstrip('\0') # Use /proc/self/fd if available if os.path.lexists("/proc/self/fd/"): return os.readlink("/proc/self/fd/%s" % fp.fd) # Fallback to /dev/fd if os.path.lexists("/dev/fd/"): return os.readlink("/dev/fd/%s" % fp.fd) raise NotImplementedError('Environment not supported (fdescfs not mounted?)') @classmethod def seek(cls, fp, offset, origin): """ :type fp: asio.interfaces.posix.PosixFile :type offset: int :type origin: int """ os.lseek(fp.fd, offset, origin) @classmethod def read(cls, fp, n=DEFAULT_BUFFER_SIZE): """ :type fp: asio.interfaces.posix.PosixFile :type n: int :rtype: str """ r, w, x = select.select([fp.fd], [], [], 5) if r: return os.read(fp.fd, n) return None @classmethod def close(cls, fp): """ :type fp: asio.interfaces.posix.PosixFile """ os.close(fp.fd) class PosixFile(File): platform_handler = PosixInterface def __init__(self, fd, *args, **kwargs): """ :type fd: asio.file.File """ super(PosixFile, self).__init__(*args, **kwargs) self.fd = fd def __str__(self): return "" % self.fd