if(getFileSystem().isReadOnly()) { throw new ReadOnlyFileSystemException("write in readonly filesystem"); }
    public void write(long fileOffset, byte[] src, int off, int len)            throws IOException {        //synchronize to the inode cache to make sure that the inode does not        // get        //flushed between reading it and locking it        synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {            //reread the inode before synchronizing to it to make sure            //all threads use the same instance            rereadInode();            //lock the inode into the cache so it is not flushed before            // synchronizing to it            //(otherwise a new instance of INode referring to the same inode            // could be put            //in the cache resulting in the possibility of two threads            // manipulating the same            //inode at the same time because they would synchronize to            // different INode instances)            iNode.incLocked();        }        try {            //a single inode may be represented by more than one Ext2File            // instances,            //but each will use the same instance of the underlying inode (see            // Ext2FileSystem.getINode()),            //so synchronize to the inode            synchronized (iNode) {                if (fileOffset > getLength())                    throw new IOException(                            "Can't write beyond the end of the file! (fileOffset: "                                    + fileOffset + ", getLength()"                                    + getLength());                if (off + len > src.length)                    throw new IOException(                            "src is shorter than what you want to write");                log.debug("write(fileOffset=" + fileOffset + ", src, off, len="                        + len + ")");                final long blockSize = iNode.getExt2FileSystem().getBlockSize();                long blocksAllocated = iNode.getAllocatedBlockCount();                long bytesWritten = 0;                while (bytesWritten < len) {                    long blockIndex = (fileOffset + bytesWritten) / blockSize;                    long blockOffset = (fileOffset + bytesWritten) % blockSize;                    long copyLength = Math.min(len - bytesWritten, blockSize                            - blockOffset);                    //If only a part of the block is written, then read the                    // block                    //and update its contents with the data in src. If the                    // whole block                    //is overwritten, then skip reading it.                    byte[] dest;                    if (!((blockOffset == 0) && (copyLength == blockSize))                            && (blockIndex < blocksAllocated))                        dest = iNode.getDataBlock(blockIndex);                    else                        dest = new byte[(int) blockSize];                    System.arraycopy(src, (int) (off + bytesWritten), dest,                            (int) blockOffset, (int) copyLength);                    //allocate a new block if needed                    if (blockIndex >= blocksAllocated) {                        try {                            iNode.allocateDataBlock(blockIndex);                        } catch (FileSystemException ex) {                            final IOException ioe = new IOException("Internal filesystem exception");                            ioe.initCause(ex);                            throw ioe;                        }                        blocksAllocated++;                    }                    //write the block                    iNode.writeDataBlock(blockIndex, dest);                    bytesWritten += copyLength;                }                iNode.setSize(fileOffset + len);                iNode.setMtime(System.currentTimeMillis() / 1000);            }        } catch (Throwable ex) {            final IOException ioe = new IOException();            ioe.initCause(ex);            throw ioe;        } finally {            //write done, unlock the inode from the cache            iNode.decLocked();                    }    }