Mercurial > hg > Members > kono > jpf-core
view src/peers/gov/nasa/jpf/vm/JPF_java_io_FileDescriptor.java @ 0:61d41facf527
initial v8 import (history reset)
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 23 Jan 2015 10:14:01 -0800 |
parents | |
children |
line wrap: on
line source
/* * Copyright (C) 2014, United States Government, as represented by the * Administrator of the National Aeronautics and Space Administration. * All rights reserved. * * The Java Pathfinder core (jpf-core) platform is 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. */ package gov.nasa.jpf.vm; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPF; import gov.nasa.jpf.annotation.MJI; import gov.nasa.jpf.util.DynamicObjectArray; import gov.nasa.jpf.util.JPFLogger; import gov.nasa.jpf.vm.MJIEnv; import gov.nasa.jpf.vm.NativePeer; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; /** * native peer for file descriptors, which are our basic interface to * access file contents. The implementation used here just forwards * to FileInputStreams, which is terribly inefficient for frequent * restores (in which case a simple byte[] buffer would be more efficient) */ public class JPF_java_io_FileDescriptor extends NativePeer { static JPFLogger logger = JPF.getLogger("java.io.FileDescriptor"); // NOTE: keep those in sync with the model class static final int FD_READ = 0; static final int FD_WRITE = 1; static final int FD_NEW = 0; static final int FD_OPENED = 1; static final int FD_CLOSED = 2; int count=2; // count out std handles DynamicObjectArray<Object> content; public JPF_java_io_FileDescriptor (Config conf){ content = new DynamicObjectArray<Object>(); count = 2; } @MJI public int open__Ljava_lang_String_2I__I (MJIEnv env, int objref, int fnameRef, int mode){ String fname = env.getStringObject(fnameRef); if (mode == FD_READ){ return openRead(fname); } else if (mode == FD_WRITE){ return openWrite(fname); } else { env.throwException("java.io.IOException", "illegal open mode: " + mode); return -1; } } @MJI public int openRead (String fname) { File file = new File(fname); if (file.exists()) { try { FileInputStream fis = new FileInputStream(file); fis.getChannel(); // just to allocate one count++; content.set(count, fis); logger.info("opening ", fname, " (read) => ", count); return count; } catch (IOException x) { logger.warning("failed to open ", fname, " (read) : ", x); } } else { logger.info("cannot open ", fname, " (read) : file not found"); } return -1; } @MJI public int openWrite (String fname){ File file = new File(fname); try { FileOutputStream fos = new FileOutputStream(file); fos.getChannel(); // just to allocate one count++; content.set(count, fos); logger.info("opening ", fname, " (write) => ", count); return count; } catch (IOException x) { logger.warning("failed to open ", fname, " (write) : ", x); } return -1; } @MJI public void close0 (MJIEnv env, int objref) { int fd = env.getIntField(objref, "fd"); try { Object fs = content.get(fd); if (fs != null){ logger.info("closing ", fd); if (fs instanceof FileInputStream){ ((FileInputStream)fs).close(); } else { ((FileOutputStream)fs).close(); } } else { logger.warning("cannot close ", fd, " : no such stream"); } content.set(fd, null); } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); } } // that's a JPF specific thing - we backrack into // a state where the file was still open, and hence don't want to // change the FileDescriptor identify void reopen (MJIEnv env, int objref) throws IOException { int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); if (content.get(fd) == null){ int mode = env.getIntField(objref, "mode"); int fnRef = env.getReferenceField(objref, "fileName"); String fname = env.getStringObject(fnRef); if (mode == FD_READ){ FileInputStream fis = new FileInputStream(fname); FileChannel fc = fis.getChannel(); // just to allocate one fc.position(off); content.set(fd, fis); } else if (mode == FD_WRITE){ FileOutputStream fos = new FileOutputStream(fname); FileChannel fc = fos.getChannel(); // just to allocate one fc.position(off); content.set(fd, fos); } else { env.throwException("java.io.IOException", "illegal mode: " + mode); } } } @MJI public void write__I__ (MJIEnv env, int objref, int b){ int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { // this is terrible overhead Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileOutputStream){ FileOutputStream fos = (FileOutputStream)fs; FileChannel fc = fos.getChannel(); fc.position(off); fos.write(b); env.setLongField(objref, "off", fc.position()); } else { env.throwException("java.io.IOException", "write attempt on file opened for read access"); } } else { if (env.getIntField(objref, "state") == FD_OPENED){ // backtracked reopen(env,objref); write__I__(env,objref,b); // try again } else { env.throwException("java.io.IOException", "write attempt on closed file"); } } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); } } @MJI public void write___3BII__ (MJIEnv env, int objref, int bref, int offset, int len){ int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { // this is terrible overhead Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileOutputStream){ FileOutputStream fos = (FileOutputStream)fs; FileChannel fc = fos.getChannel(); fc.position(off); byte[] buf = new byte[len]; // <2do> make this a permanent buffer for (int i=0, j=offset; i<len; i++, j++){ buf[i] = env.getByteArrayElement(bref, j); } fos.write(buf); env.setLongField(objref, "off", fc.position()); } else { env.throwException("java.io.IOException", "write attempt on file opened for read access"); } } else { if (env.getIntField(objref, "state") == FD_OPENED){ // backtracked reopen(env,objref); write___3BII__(env,objref,bref,offset,len); // try again } else { env.throwException("java.io.IOException", "write attempt on closed file"); } } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); } } @MJI public int read____I (MJIEnv env, int objref) { int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { // this is terrible overhead Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileInputStream){ FileInputStream fis = (FileInputStream)fs; FileChannel fc = fis.getChannel(); fc.position(off); int r = fis.read(); env.setLongField(objref, "off", fc.position()); return r; } else { env.throwException("java.io.IOException", "read attempt on file opened for write access"); return -1; } } else { if (env.getIntField(objref, "state") == FD_OPENED){ // backtracked reopen(env,objref); return read____I(env,objref); // try again } else { env.throwException("java.io.IOException", "read attempt on closed file"); return -1; } } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); return -1; } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); return -1; } } @MJI public int read___3BII__I (MJIEnv env, int objref, int bufref, int offset, int len) { int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileInputStream){ FileInputStream fis = (FileInputStream)fs; FileChannel fc = fis.getChannel(); fc.position(off); byte[] buf = new byte[len]; // <2do> make this a permanent buffer int r = fis.read(buf); for (int i=0, j=offset; i<len; i++, j++) { env.setByteArrayElement(bufref, j, buf[i]); } env.setLongField(objref, "off", fc.position()); return r; } else { env.throwException("java.io.IOException", "read attempt on file opened for write access"); return -1; } } else { if (env.getIntField(objref, "state") == FD_OPENED){ // backtracked reopen(env,objref); return read___3BII__I(env,objref,bufref,offset,len); // try again } else { env.throwException("java.io.IOException", "read attempt on closed file"); return -1; } } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); return -1; } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); return -1; } } @MJI public long skip__J__J (MJIEnv env, int objref, long nBytes) { int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileInputStream){ FileInputStream fis = (FileInputStream)fs; FileChannel fc = fis.getChannel(); fc.position(off); long r = fis.skip(nBytes); env.setLongField(objref, "off", fc.position()); return r; } else { env.throwException("java.io.IOException", "skip attempt on file opened for write access"); return -1; } } else { env.throwException("java.io.IOException", "skip attempt on closed file"); return -1; } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); return -1; } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); return -1; } } @MJI public void sync____ (MJIEnv env, int objref){ int fd = env.getIntField(objref, "fd"); try { Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileOutputStream){ ((FileOutputStream)fs).flush(); } else { // nothing } } else { env.throwException("java.io.IOException", "sync attempt on closed file"); } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); } } @MJI public int available____I (MJIEnv env, int objref) { int fd = env.getIntField(objref, "fd"); long off = env.getLongField(objref,"off"); try { Object fs = content.get(fd); if (fs != null){ if (fs instanceof FileInputStream){ FileInputStream fis = (FileInputStream)fs; FileChannel fc = fis.getChannel(); fc.position(off); return fis.available(); } else { env.throwException("java.io.IOException", "available() on file opened for write access"); return -1; } } else { env.throwException("java.io.IOException", "available() on closed file"); return -1; } } catch (ArrayIndexOutOfBoundsException aobx){ env.throwException("java.io.IOException", "file not open"); return -1; } catch (IOException iox) { env.throwException("java.io.IOException", iox.getMessage()); return -1; } } }