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 1952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesimport dalvik.system.BlockGuard; 205112325117859c7c6cd042c17f519f967c551b20Jesse Wilsonimport dalvik.system.SocketTagger; 2152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesimport java.io.FileDescriptor; 22996bf79565ac88402920bd826d6f85952c83be20Elliott Hughesimport java.net.InetAddress; 2323ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughesimport java.net.InetSocketAddress; 241e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkeyimport java.net.SocketException; 2526c7025a7a919044771fb89031161bd26fe03032Elliott Hughesimport java.nio.ByteBuffer; 260ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughesimport static libcore.io.OsConstants.*; 2752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes 2852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes/** 2952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes * Informs BlockGuard of any activity it should be aware of. 3052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes */ 3152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughespublic class BlockGuardOs extends ForwardingOs { 3252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes public BlockGuardOs(Os os) { 3352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes super(os); 3452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes } 3552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes 369b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes private FileDescriptor tagSocket(FileDescriptor fd) throws ErrnoException { 37553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes try { 385112325117859c7c6cd042c17f519f967c551b20Jesse Wilson SocketTagger.get().tag(fd); 39553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes return fd; 40553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } catch (SocketException e) { 41553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes throw new ErrnoException("socket", EINVAL, e); 42553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 43553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 44553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 454ff585466887785d48c02d14a15dcde64934442bJP Abgrall private void untagSocket(FileDescriptor fd) throws ErrnoException { 464ff585466887785d48c02d14a15dcde64934442bJP Abgrall try { 474ff585466887785d48c02d14a15dcde64934442bJP Abgrall SocketTagger.get().untag(fd); 484ff585466887785d48c02d14a15dcde64934442bJP Abgrall } catch (SocketException e) { 494ff585466887785d48c02d14a15dcde64934442bJP Abgrall throw new ErrnoException("socket", EINVAL, e); 504ff585466887785d48c02d14a15dcde64934442bJP Abgrall } 514ff585466887785d48c02d14a15dcde64934442bJP Abgrall } 524ff585466887785d48c02d14a15dcde64934442bJP Abgrall 5326010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException { 54553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 55553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes return tagSocket(os.accept(fd, peerAddress)); 56553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes } 57553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes 58e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes @Override public void close(FileDescriptor fd) throws ErrnoException { 59e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes try { 604ff585466887785d48c02d14a15dcde64934442bJP Abgrall if (S_ISSOCK(Libcore.os.fstat(fd).st_mode)) { 614ff585466887785d48c02d14a15dcde64934442bJP Abgrall if (isLingerSocket(fd)) { 624ff585466887785d48c02d14a15dcde64934442bJP Abgrall // If the fd is a socket with SO_LINGER set, we might block indefinitely. 634ff585466887785d48c02d14a15dcde64934442bJP Abgrall // We allow non-linger sockets so that apps can close their network 644ff585466887785d48c02d14a15dcde64934442bJP Abgrall // connections in methods like onDestroy which will run on the UI thread. 654ff585466887785d48c02d14a15dcde64934442bJP Abgrall BlockGuard.getThreadPolicy().onNetwork(); 664ff585466887785d48c02d14a15dcde64934442bJP Abgrall } 674ff585466887785d48c02d14a15dcde64934442bJP Abgrall untagSocket(fd); 68e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes } 69e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes } catch (ErrnoException ignored) { 70e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes // We're called via Socket.close (which doesn't ask for us to be called), so we 71e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes // must not throw here, because Socket.close must not throw if asked to close an 72e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes // already-closed socket. Also, the passed-in FileDescriptor isn't necessarily 73e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes // a socket at all. 74e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes } 75e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes os.close(fd); 76e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes } 77e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes 78e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes private static boolean isLingerSocket(FileDescriptor fd) throws ErrnoException { 79e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER); 80e8e19f6476b30ccf9f69925c10ce62efdba4e62aElliott Hughes return linger.isOn() && linger.l_linger > 0; 81e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes } 82e27d02044ec399884bfd4343d513bf270b9b9b11Elliott Hughes 8326010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { 84996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 85996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes os.connect(fd, address, port); 86996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes } 87996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes 884ff585466887785d48c02d14a15dcde64934442bJP Abgrall // TODO: Untag newFd when needed for dup2(FileDescriptor oldFd, int newFd) 894ff585466887785d48c02d14a15dcde64934442bJP Abgrall 9070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes @Override public void fdatasync(FileDescriptor fd) throws ErrnoException { 9152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 9252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes os.fdatasync(fd); 9352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes } 9452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes 9590d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public void fsync(FileDescriptor fd) throws ErrnoException { 9652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 9752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes os.fsync(fd); 9852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes } 99f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes 10090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public void ftruncate(FileDescriptor fd, long length) throws ErrnoException { 101f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 102f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes os.ftruncate(fd, length); 103f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes } 1040ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes 10590d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public FileDescriptor open(String path, int flags, int mode) throws ErrnoException { 1060ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 1070ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes if ((mode & O_ACCMODE) != O_RDONLY) { 1080ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 1090ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes } 1100ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes return os.open(path, flags, mode); 1110ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes } 11226c7025a7a919044771fb89031161bd26fe03032Elliott Hughes 11370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes @Override public int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException { 1142bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes // Greater than 0 is a timeout in milliseconds and -1 means "block forever", 1152bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes // but 0 means "poll and return immediately", which shouldn't be subject to BlockGuard. 1162bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes if (timeoutMs != 0) { 1172bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 1182bad9bff258de6275bd3847e5e9f3169b0a93c61Elliott Hughes } 11970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return os.poll(fds, timeoutMs); 12070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 12170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 122e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes @Override public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException { 123e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 124e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes return os.pread(fd, buffer, offset); 125e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes } 126e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes 127e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes @Override public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException { 128e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 129e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes return os.pread(fd, bytes, byteOffset, byteCount, offset); 130e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes } 131e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes 132e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes @Override public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException { 133e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 134e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes return os.pwrite(fd, buffer, offset); 135e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes } 136e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes 137e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes @Override public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException { 138e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 139e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes return os.pwrite(fd, bytes, byteOffset, byteCount, offset); 140e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes } 141e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes 14270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes @Override public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException { 14326c7025a7a919044771fb89031161bd26fe03032Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 14426c7025a7a919044771fb89031161bd26fe03032Elliott Hughes return os.read(fd, buffer); 14526c7025a7a919044771fb89031161bd26fe03032Elliott Hughes } 14626c7025a7a919044771fb89031161bd26fe03032Elliott Hughes 14790d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException { 14826c7025a7a919044771fb89031161bd26fe03032Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 14926c7025a7a919044771fb89031161bd26fe03032Elliott Hughes return os.read(fd, bytes, byteOffset, byteCount); 15026c7025a7a919044771fb89031161bd26fe03032Elliott Hughes } 15178c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes 15290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException { 153bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes BlockGuard.getThreadPolicy().onReadFromDisk(); 154bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes return os.readv(fd, buffers, offsets, byteCounts); 155bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes } 156bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes 15726010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { 15823ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 159553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes return os.recvfrom(fd, buffer, flags, srcAddress); 16023ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes } 16123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes 16226010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException { 16323ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 164553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes return os.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress); 16523ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes } 16623ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes 16726010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { 16890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 16990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes return os.sendto(fd, buffer, flags, inetAddress, port); 17090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } 17190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes 17226010ab930a2cee3bf10b9612cf070183c21228bElliott Hughes @Override public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { 17390d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes // We permit datagrams without hostname lookups. 17490d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes if (inetAddress != null) { 17590d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes BlockGuard.getThreadPolicy().onNetwork(); 17690d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } 17790d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes return os.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port); 17890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes } 17990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes 18090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException { 181553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes return tagSocket(os.socket(domain, type, protocol)); 1821e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkey } 1831e8d508f2d97e19f2fc8a709330ea97e1e9f203aJeff Sharkey 1843218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes @Override public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException { 1853218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes os.socketpair(domain, type, protocol, fd1, fd2); 1863218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes tagSocket(fd1); 1873218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes tagSocket(fd2); 1883218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes } 1893218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes 19090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException { 19178c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 19278c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes return os.write(fd, buffer); 19378c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes } 19478c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes 19590d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException { 19678c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 19778c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes return os.write(fd, bytes, byteOffset, byteCount); 19878c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes } 199bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes 20090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes @Override public int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException { 201bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes BlockGuard.getThreadPolicy().onWriteToDisk(); 202bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes return os.writev(fd, buffers, offsets, byteCounts); 203bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes } 20452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes} 205