152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes/*
252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes *
452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * you may not use this file except in compliance with the License.
652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * You may obtain a copy of the License at
752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes *
852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes *
1052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * See the License for the specific language governing permissions and
1452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * limitations under the License.
1552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes */
1652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
1752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughespackage libcore.io;
1852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
195d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException;
205d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructLinger;
215d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructPollfd;
225d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructStat;
235d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructStatVfs;
245d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.util.MutableLong;
2552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesimport dalvik.system.BlockGuard;
265112325117859c7c6cd042c17f519f967c551b20Jesse Wilsonimport dalvik.system.SocketTagger;
2752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesimport java.io.FileDescriptor;
28f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport java.io.InterruptedIOException;
29996bf79565ac88402920bd826d6f85952c83be20Elliott Hughesimport java.net.InetAddress;
3023ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughesimport java.net.InetSocketAddress;
311e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkeyimport java.net.SocketException;
3226c7025a7a919044771fb89031161bd26fe03032Elliott Hughesimport java.nio.ByteBuffer;
335d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*;
34d636777d624428dfc51d1181f47602f389eb4cceElliott Hughesimport static dalvik.system.BlockGuard.DISALLOW_NETWORK;
3552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
3652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes/**
3752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * Informs BlockGuard of any activity it should be aware of.
3852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes */
3952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughespublic class BlockGuardOs extends ForwardingOs {
4052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    public BlockGuardOs(Os os) {
4152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes        super(os);
4252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    }
4352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
449b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes    private FileDescriptor tagSocket(FileDescriptor fd) throws ErrnoException {
45553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        try {
465112325117859c7c6cd042c17f519f967c551b20Jesse Wilson            SocketTagger.get().tag(fd);
47553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes            return fd;
48553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        } catch (SocketException e) {
49553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes            throw new ErrnoException("socket", EINVAL, e);
50553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        }
51553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    }
52553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes
534ff585466887785d48c02d14a15dcde64934442bJP Abgrall    private void untagSocket(FileDescriptor fd) throws ErrnoException {
544ff585466887785d48c02d14a15dcde64934442bJP Abgrall        try {
554ff585466887785d48c02d14a15dcde64934442bJP Abgrall            SocketTagger.get().untag(fd);
564ff585466887785d48c02d14a15dcde64934442bJP Abgrall        } catch (SocketException e) {
574ff585466887785d48c02d14a15dcde64934442bJP Abgrall            throw new ErrnoException("socket", EINVAL, e);
584ff585466887785d48c02d14a15dcde64934442bJP Abgrall        }
594ff585466887785d48c02d14a15dcde64934442bJP Abgrall    }
604ff585466887785d48c02d14a15dcde64934442bJP Abgrall
6126010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException {
62553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        BlockGuard.getThreadPolicy().onNetwork();
63553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return tagSocket(os.accept(fd, peerAddress));
64553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    }
65553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes
66edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public boolean access(String path, int mode) throws ErrnoException {
67edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
68edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.access(path, mode);
69edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
70edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
71edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void chmod(String path, int mode) throws ErrnoException {
72edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
73edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.chmod(path, mode);
74edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
75edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
76edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void chown(String path, int uid, int gid) throws ErrnoException {
77edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
78edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.chown(path, uid, gid);
79edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
80edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
81e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes    @Override public void close(FileDescriptor fd) throws ErrnoException {
82e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes        try {
83f6cf9efb212e572dcd2e902ca461af6323793dbfElliott Hughes            // The usual case is that this _isn't_ a socket, so the getsockopt(2) call in
84f6cf9efb212e572dcd2e902ca461af6323793dbfElliott Hughes            // isLingerSocket will throw, and that's really expensive. Try to avoid asking
85f6cf9efb212e572dcd2e902ca461af6323793dbfElliott Hughes            // if we don't care.
86f6cf9efb212e572dcd2e902ca461af6323793dbfElliott Hughes            if (fd.isSocket()) {
874ff585466887785d48c02d14a15dcde64934442bJP Abgrall                if (isLingerSocket(fd)) {
884ff585466887785d48c02d14a15dcde64934442bJP Abgrall                    // If the fd is a socket with SO_LINGER set, we might block indefinitely.
894ff585466887785d48c02d14a15dcde64934442bJP Abgrall                    // We allow non-linger sockets so that apps can close their network
904ff585466887785d48c02d14a15dcde64934442bJP Abgrall                    // connections in methods like onDestroy which will run on the UI thread.
914ff585466887785d48c02d14a15dcde64934442bJP Abgrall                    BlockGuard.getThreadPolicy().onNetwork();
924ff585466887785d48c02d14a15dcde64934442bJP Abgrall                }
93f6cf9efb212e572dcd2e902ca461af6323793dbfElliott Hughes                untagSocket(fd);
94e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes            }
95e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes        } catch (ErrnoException ignored) {
96e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes            // We're called via Socket.close (which doesn't ask for us to be called), so we
97e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes            // must not throw here, because Socket.close must not throw if asked to close an
98e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes            // already-closed socket. Also, the passed-in FileDescriptor isn't necessarily
99e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes            // a socket at all.
100e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes        }
101e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes        os.close(fd);
102e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes    }
103e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes
104e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes    private static boolean isLingerSocket(FileDescriptor fd) throws ErrnoException {
105e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes        StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
106e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes        return linger.isOn() && linger.l_linger > 0;
107e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes    }
108e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes
10926010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException {
110996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes        BlockGuard.getThreadPolicy().onNetwork();
111996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes        os.connect(fd, address, port);
112996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes    }
113996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes
114edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void fchmod(FileDescriptor fd, int mode) throws ErrnoException {
115edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
116edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.fchmod(fd, mode);
117edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
118edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
119edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException {
120edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
121edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.fchown(fd, uid, gid);
122edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
123edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
1244ff585466887785d48c02d14a15dcde64934442bJP Abgrall    // TODO: Untag newFd when needed for dup2(FileDescriptor oldFd, int newFd)
1254ff585466887785d48c02d14a15dcde64934442bJP Abgrall
12670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    @Override public void fdatasync(FileDescriptor fd) throws ErrnoException {
12752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
12852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes        os.fdatasync(fd);
12952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    }
13052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
131edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public StructStat fstat(FileDescriptor fd) throws ErrnoException {
132edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
133edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.fstat(fd);
134edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
135edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
136edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException {
137edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
138edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.fstatvfs(fd);
139edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
140edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
14190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    @Override public void fsync(FileDescriptor fd) throws ErrnoException {
14252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
14352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes        os.fsync(fd);
14452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    }
145f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes
14690d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    @Override public void ftruncate(FileDescriptor fd, long length) throws ErrnoException {
147f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
148f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes        os.ftruncate(fd, length);
149f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes    }
1500ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes
151edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void lchown(String path, int uid, int gid) throws ErrnoException {
152edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
153edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.lchown(path, uid, gid);
154edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
155edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
15604428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    @Override public void link(String oldPath, String newPath) throws ErrnoException {
15704428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
15804428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes        os.link(oldPath, newPath);
15904428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    }
16004428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes
161edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
162edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
163edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.lseek(fd, offset, whence);
164edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
165edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
166edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public StructStat lstat(String path) throws ErrnoException {
167edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
168edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.lstat(path);
169edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
170edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
171edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void mkdir(String path, int mode) throws ErrnoException {
172edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
173edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.mkdir(path, mode);
174edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
175edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
176f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public void mkfifo(String path, int mode) throws ErrnoException {
177f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        BlockGuard.getThreadPolicy().onWriteToDisk();
178f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        os.mkfifo(path, mode);
179f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    }
180f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller
18190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    @Override public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
1820ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
1830ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes        if ((mode & O_ACCMODE) != O_RDONLY) {
1840ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes            BlockGuard.getThreadPolicy().onWriteToDisk();
1850ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes        }
1860ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes        return os.open(path, flags, mode);
1870ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    }
18826c7025a7a919044771fb89031161bd26fe03032Elliott Hughes
18970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    @Override public int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException {
1902bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes        // Greater than 0 is a timeout in milliseconds and -1 means "block forever",
1912bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes        // but 0 means "poll and return immediately", which shouldn't be subject to BlockGuard.
1922bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes        if (timeoutMs != 0) {
1932bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes            BlockGuard.getThreadPolicy().onNetwork();
1942bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes        }
19570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        return os.poll(fds, timeoutMs);
19670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    }
19770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes
19811f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    @Override public void posix_fallocate(FileDescriptor fd, long offset, long length) throws ErrnoException {
19911f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
20011f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes        os.posix_fallocate(fd, offset, length);
20111f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    }
20211f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes
203f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
204e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
205e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return os.pread(fd, buffer, offset);
206e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
207e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
208f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
209e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
210e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return os.pread(fd, bytes, byteOffset, byteCount, offset);
211e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
212e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
213f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
214e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
215e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return os.pwrite(fd, buffer, offset);
216e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
217e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
218f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
219e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
220e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return os.pwrite(fd, bytes, byteOffset, byteCount, offset);
221e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
222e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
223f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
22426c7025a7a919044771fb89031161bd26fe03032Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
22526c7025a7a919044771fb89031161bd26fe03032Elliott Hughes        return os.read(fd, buffer);
22626c7025a7a919044771fb89031161bd26fe03032Elliott Hughes    }
22726c7025a7a919044771fb89031161bd26fe03032Elliott Hughes
228f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
22926c7025a7a919044771fb89031161bd26fe03032Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
23026c7025a7a919044771fb89031161bd26fe03032Elliott Hughes        return os.read(fd, bytes, byteOffset, byteCount);
23126c7025a7a919044771fb89031161bd26fe03032Elliott Hughes    }
23278c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes
2330b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    @Override public String readlink(String path) throws ErrnoException {
2340b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes      BlockGuard.getThreadPolicy().onReadFromDisk();
2350b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes      return os.readlink(path);
2360b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    }
2370b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes
238f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
239bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        BlockGuard.getThreadPolicy().onReadFromDisk();
240bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return os.readv(fd, buffers, offsets, byteCounts);
241bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
242bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
24326010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
24423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        BlockGuard.getThreadPolicy().onNetwork();
245553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return os.recvfrom(fd, buffer, flags, srcAddress);
24623ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    }
24723ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes
24826010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
24923ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        BlockGuard.getThreadPolicy().onNetwork();
250553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return os.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress);
25123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    }
25223ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes
253edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void remove(String path) throws ErrnoException {
254edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
255edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.remove(path);
256edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
257edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
258edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void rename(String oldPath, String newPath) throws ErrnoException {
259edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
260edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.rename(oldPath, newPath);
261edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
262edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
263edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException {
264edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
265edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.sendfile(outFd, inFd, inOffset, byteCount);
266edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
267edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
26826010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
26990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        BlockGuard.getThreadPolicy().onNetwork();
27090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        return os.sendto(fd, buffer, flags, inetAddress, port);
27190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    }
27290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes
27326010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes    @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
27490d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        // We permit datagrams without hostname lookups.
27590d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        if (inetAddress != null) {
27690d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes            BlockGuard.getThreadPolicy().onNetwork();
27790d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        }
27890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        return os.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port);
27990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    }
28090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes
28190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    @Override public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException {
282553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return tagSocket(os.socket(domain, type, protocol));
2831e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkey    }
2841e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkey
2853218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    @Override public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException {
2863218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        os.socketpair(domain, type, protocol, fd1, fd2);
2873218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        tagSocket(fd1);
2883218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        tagSocket(fd2);
2893218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    }
2903218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes
291edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public StructStat stat(String path) throws ErrnoException {
292edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
293edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.stat(path);
294edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
295edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
296edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public StructStatVfs statvfs(String path) throws ErrnoException {
297edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onReadFromDisk();
298edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        return os.statvfs(path);
299edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
300edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
301edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    @Override public void symlink(String oldPath, String newPath) throws ErrnoException {
302edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        BlockGuard.getThreadPolicy().onWriteToDisk();
303edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey        os.symlink(oldPath, newPath);
304edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey    }
305edaa74db58376b7528434707304d081591df2fb5Jeff Sharkey
306f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
30778c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
30878c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes        return os.write(fd, buffer);
30978c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes    }
31078c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes
311f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
31278c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
31378c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes        return os.write(fd, bytes, byteOffset, byteCount);
31478c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes    }
315bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
316f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    @Override public int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException {
317bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        BlockGuard.getThreadPolicy().onWriteToDisk();
318bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return os.writev(fd, buffers, offsets, byteCounts);
319bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
32052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes}
321