blob: 7a49f0b213ba58880aeba2093eeb4fdda3496087 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Base interface for file API.
#ifndef POSIX_TRANSLATION_FILE_STREAM_H_
#define POSIX_TRANSLATION_FILE_STREAM_H_
#include <dirent.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/mman.h> // MAP_FAILED
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/vfs.h>
#include <termios.h>
#include <unistd.h>
#include <map>
#include <string>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "common/arc_strace.h"
#include "posix_translation/permission_info.h"
namespace posix_translation {
class FileStream : public base::RefCounted<FileStream> {
public:
FileStream(int oflag, const std::string& pathname);
const PermissionInfo& permission() const {
return permission_;
}
void set_permission(const PermissionInfo& permission) {
permission_ = permission;
}
virtual bool IsAllowedOnMainThread() const;
// Returns true if FileStream that returns the same address when mmap() is
// called twice or more. Such a stream needs a special handling in
// MemoryRegion.
virtual bool ReturnsSameAddressForMultipleMmaps() const;
// Adds a file reference to allow the object to call OnLastFileRef() later
// when the file reference count is dropped to zero.
void AddFileRef();
// Releases a file reference. OnLastFileRef() might be called.
void ReleaseFileRef();
// Sorted by syscall name.
virtual int accept(sockaddr* addr, socklen_t* addrlen);
virtual int bind(const sockaddr* addr, socklen_t addrlen);
virtual int connect(const sockaddr* addr, socklen_t addrlen);
virtual int epoll_ctl(
int op, scoped_refptr<FileStream> file, struct epoll_event* event);
virtual int epoll_wait(struct epoll_event* events, int maxevents,
int timeout);
virtual int fcntl(int cmd, va_list ap);
virtual int fdatasync();
virtual int fstat(struct stat* out);
virtual int fstatfs(struct statfs* out);
virtual int fsync();
virtual int ftruncate(off64_t length);
virtual int getdents(dirent* buf, size_t count);
virtual int getpeername(sockaddr* name, socklen_t* namelen);
virtual int getsockname(sockaddr* name, socklen_t* namelen);
virtual int getsockopt(int level, int optname, void* optval,
socklen_t* optlen);
virtual int ioctl(int request, va_list ap);
virtual int listen(int backlog);
virtual off64_t lseek(off64_t offset, int whence);
// If madvise returns 1, VFS should abort immediately.
virtual int madvise(void* addr, size_t length, int advice);
virtual void* mmap(
void* addr, size_t length, int prot, int flags, off_t offset);
// If mprotect returns 1, VFS should abort immediately.
virtual int mprotect(void* addr, size_t length, int prot);
virtual int munmap(void* addr, size_t length);
virtual ssize_t pread(void* buf, size_t count, off64_t offset);
virtual ssize_t read(void* buf, size_t count) = 0;
virtual int readv(const struct iovec* iov, int count);
virtual ssize_t recv(void* buf, size_t len, int flags);
virtual ssize_t recvfrom(void* buf, size_t len, int flags, sockaddr* addr,
socklen_t* addrlen);
virtual int recvmsg(struct msghdr* msg, int flags);
virtual ssize_t send(const void* buf, size_t len, int flags);
virtual ssize_t sendto(const void* buf, size_t len, int flags,
const sockaddr* dest_addr, socklen_t addrlen);
virtual int sendmsg(const struct msghdr* msg, int flags);
virtual int setsockopt(int level, int optname, const void* optval,
socklen_t optlen);
// Note: In write() and writev(), do not call any function which
// directly or indirectly calls ::write() or libc's write().
// It will be trapped at IRT layer and may loop back to VirtualFileSystem and
// FileStream. printf() and fprintf() are good examples. ARC logging
// functions in common/alog.h and common/arc_strace.h are safe to call.
virtual ssize_t write(const void* buf, size_t count) = 0;
virtual int writev(const struct iovec* iov, int count);
// For the implementation of select().
// Streams which support select must override these 3 functions.
// Implementations of these IsSelect*Ready() functions *must* return
// immediately without communicating with the main thread. Otherwise, select
// syscall families with short timeout might not work as expected.
virtual bool IsSelectReadReady() const;
virtual bool IsSelectWriteReady() const;
virtual bool IsSelectExceptionReady() const;
// For the implementation of poll().
// Returns the bits of poll events, e.g. (POLLIN | POLLOUT).
// This function *must* return immediately without communicating with the
// main thread.
virtual int16_t GetPollEvents() const;
// TODO(crbug.com/359400): Currently, poll uses IsSelect*Ready() family
// incorrectly, due to historical reason. Fix the implementation.
// Called when the memory region [addr, addr+length) associated when the
// stream is implicitly unmapped without munmap. This happens with the
// region is overwritten by another mmap call with MAP_FIXED. File handlers
// that do not support the implicit unmap with MAP_FIXED should override
// this function to call abort.
// TODO(crbug.com/418801): Remove once we fix 418801 and change dev_ashmem.cc
// to use a shared memory IRT which does not exist today.
virtual void OnUnmapByOverwritingMmap(void* addr, size_t length);
// For debugging.
virtual const char* GetStreamType() const = 0;
virtual size_t GetSize() const;
virtual std::string GetAuxInfo() const;
// A debug-only version of write used for saving stdout/stderr logs to disk.
virtual void debug_write(const void* buf, size_t count) {}
// A non-virtual wrapper around write() and PwriteImpl().
ssize_t pwrite(const void* buf, size_t count, off64_t offset);
// Debug check verifying that this file has not lost its last reference.
void CheckNotClosed() const;
int oflag() const { return oflag_; }
void set_oflag(int oflag) { oflag_ = oflag; }
ino_t inode() const { return inode_; }
const std::string& pathname() const { return pathname_; }
protected:
friend class base::RefCounted<FileStream>;
virtual ~FileStream();
// Invoked by the non-virtual pwrite() above.
virtual ssize_t PwriteImpl(const void* buf, size_t count, off64_t offset);
// Invoked upon release of the last file reference.
virtual void OnLastFileRef();
// TODO(crbug.com/284239): Functions below are mostly for socket
// related classes. Create a base class for them and move them to
// the new class.
// Allows this file to be listened to.
void EnableListenerSupport() {
is_listening_enabled_ = true;
}
// Listener invokes this on itself to start listening to a particular file.
// Returns false if file does not support listeners (cannot notify them).
bool StartListeningTo(scoped_refptr<FileStream> file);
// Listener invokes this on itself to stop listening to a particular file.
void StopListeningTo(scoped_refptr<FileStream> file);
// Notifies all registered listeners.
void NotifyListeners();
// Called on listener to notify about a change in file.
virtual void HandleNotificationFrom(
scoped_refptr<FileStream> file, bool is_closing);
// Returns true if this file has lost its last reference.
bool IsClosed() const;
private:
// The key is FileStream*, obfuscated to avoid direct use.
typedef std::map<void*, scoped_refptr<FileStream> > FileMap;
int oflag_;
// -1 when the stream is not associated with a file (e.g. socket).
ino_t inode_;
// "" when the stream is not associated with a file (e.g. socket).
const std::string pathname_;
bool is_listening_enabled_;
FileMap listeners_;
// Permission of this file. VirtualFileSystem sets this value for
// FileStream created by FileSystemHandler. Other FileStream should fill
// this by themselves.
PermissionInfo permission_;
// The number of open-file references this stream currently has.
// It is different from base::RefCounted, as the latter merely counts
// the code references and prevents the object from being destroyed.
// file_ref_count_, on the other hand, allows tracking of the actual
// use count, such as with open or duplicated fd's.
int file_ref_count_;
// True if this stream ever had positive file_ref_count_.
// This field is needed for integrity checks only.
bool had_file_refs_;
};
} // namespace posix_translation
#endif // POSIX_TRANSLATION_FILE_STREAM_H_