////
//// Copyright (C) 20037 United States Government as represented by the
//// Administrator of the National Aeronautics and Space Administration
//// (NASA). All Rights Reserved.
////
//// This software is distributed under the NASA Open Source Agreement
//// (NOSA), version 1.3. The NOSA has been approved by the Open Source
//// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
//// directory tree for the complete NOSA document.
////
//// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
//// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
//// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
//// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
//// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
//// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
//// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
////
//package gov.nasa.jpf.vm;
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.nio.channels.FileChannel;
//import java.util.List;
//import java.util.Map.Entry;
//
//import java.util.function.BiFunction;
//import cmu.conditional.Conditional;
//import cmu.conditional.IChoice;
//import cmu.conditional.One;
//import de.fosd.typechef.featureexpr.FeatureExpr;
//import de.fosd.typechef.featureexpr.FeatureExprFactory;
//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;
//
///**
// * 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)
// */
//@SuppressWarnings({"resource", "deprecation"})
//public class JPF_java_io_FileDescriptor2 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_FileDescriptor2 (Config conf){
// content = new DynamicObjectArray<Object>();
// count = 2;
// }
//
// @MJI
// public Conditional<Integer> open__Ljava_lang_String_2I__I (MJIEnv env, int objref,
// int fnameRef, int mode, final FeatureExpr ctx) {
//// String fname = env.getStringObject(ctx, fnameRef);
// Conditional<String> fnames = env.getConditionalStringObject(fnameRef);
// final int finalMode = mode;
// final MJIEnv finalEnv = env;
// Conditional<Integer> fds = fnames.mapf(ctx, new BiFunction<FeatureExpr, String, Conditional<Integer>>() {
// @Override
// public Conditional<Integer> apply(FeatureExpr x, String y) {
// if (finalMode == FD_READ) {
// return new One<>(openRead(y, x.and(ctx)));
// } else if (finalMode == FD_WRITE) {
// return new One<>(openWrite(y, x.and(ctx)));
// } else {
// finalEnv.throwException(ctx, "java.io.IOException", "illegal open mode: " + finalMode);
// return One.valueOf(-1);
// }
// }
// });
// return fds;
// }
//
// @MJI
// public int openRead (String fname, FeatureExpr ctx) {
// 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, FeatureExpr ctx){
// 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;
// }
//
// private static Object CLOSED_OBJECT = new Object();
//
// @MJI
// public void close0 (MJIEnv env, int objref, FeatureExpr ctx) {
//// int fd = env.getIntField(objref, "fd").simplify(ctx).getValue().intValue();
// Conditional<Integer> fds = env.getIntField(objref, "fd").simplify(ctx);
//
// List<Integer> fdList = fds.toList();
// for (int fd : fdList) {
// try {
// Object fs = content.get(fd);
//
// if (fs != null){
// if (fs == CLOSED_OBJECT) {
// return;
// }
// if (fs instanceof FileInputStream){
// ((FileInputStream)fs).close();
// } else {
// ((FileOutputStream)fs).close();
// }
// } else {
// logger.warning("cannot close ", fd, " : no such stream");
// }
// content.set(fd, CLOSED_OBJECT);
//
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// } catch (IOException iox) {
// env.throwException(ctx, "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, FeatureExpr ctx) throws IOException {
// int fd = env.getIntField(objref, "fd").getValue().intValue();
// long off = env.getLongField(objref,"off").getValue();
//
// if (content.get(fd) == null){
// int mode = env.getIntField(objref, "mode").getValue().intValue();
// int fnRef = env.getReferenceField(ctx, objref, "fileName").getValue();
// String fname = env.getStringObject(ctx, 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(ctx, "java.io.IOException", "illegal mode: " + mode);
// }
// }
// }
//
// @MJI
// public void write__I__ (MJIEnv env, int objref, int b, FeatureExpr ctx){
// int fd = env.getIntField(objref, "fd").getValue().intValue();
// long off = env.getLongField(objref,"off").getValue();
//
// 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(ctx, objref, "off", new One<>(fc.position()));
//
// } else {
// env.throwException(ctx, "java.io.IOException", "write attempt on file opened for read access");
// }
//
// } else {
// if (env.getIntField(objref, "state").getValue().intValue() == FD_OPENED){ // backtracked
// reopen(env,objref, ctx);
// write__I__(env,objref,b, ctx); // try again
// } else {
// env.throwException(ctx, "java.io.IOException", "write attempt on closed file");
// }
// }
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// }
// }
//
// private static FeatureExpr bufferCTX = FeatureExprFactory.True();
//
// @MJI
// public void write___3BII__ (MJIEnv env, int objref,
// int bref, int offset, int len, FeatureExpr ctx){
// int fd = env.getIntField(objref, "fd").simplify(ctx).getValue();
// long off = env.getLongField(objref,"off").simplify(ctx).getValue();
//
// 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++){
// Conditional<Byte> value = env.getByteArrayElement(bref, j).simplify(ctx).simplify(bufferCTX);
// if (value instanceof IChoice) {
// for (Entry<Byte, FeatureExpr> entry : value.toMap().entrySet()) {
// System.err.println("JPF_java_io_FileDescriptor.write___3BII__()");
// System.err.println("Conditional write"+ value);
// bufferCTX = entry.getValue();
// System.err.println("Set write ctx to: " + bufferCTX);
// buf[i] = entry.getKey();
// break;
// }
// } else {
// buf[i] = value.getValue();
// }
// }
// fos.write(buf);
//
// env.setLongField(ctx, objref, "off", new One<>(fc.position()));
//
// } else {
// env.throwException(ctx, "java.io.IOException", "write attempt on file opened for read access");
// }
//
// } else {
// if (env.getIntField(objref, "state").getValue().intValue() == FD_OPENED){ // backtracked
// reopen(env,objref, ctx);
// write___3BII__(env,objref,bref,offset,len, ctx); // try again
// } else {
// env.throwException(ctx, "java.io.IOException", "write attempt on closed file");
// }
// }
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// }
// }
//
// @MJI
// public int read____I (MJIEnv env, int objref, FeatureExpr ctx) {
// try {
// int fd = env.getIntField(objref, "fd").getValue();
// long off = env.getLongField(objref,"off").simplify(ctx).getValue();
//
// // 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(ctx, objref, "off", new One<>(fc.position()));
// return r;
// } else {
// env.throwException(ctx, "java.io.IOException", "read attempt on file opened for write access");
// return -1;
// }
//
// } else {
// if (env.getIntField(objref, "state").getValue().intValue() == FD_OPENED){ // backtracked
// reopen(env,objref, ctx);
// return read____I(env,objref, ctx); // try again
// } else {
// env.throwException(ctx, "java.io.IOException", "read attempt on closed file");
// return -1;
// }
// }
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// return -1;
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// } catch (Exception e) {
// env.throwException(ctx, Exception.class.getName(), e.getMessage());
// }
// return -1;
// }
//
// @MJI
// public int read___3BII__I(MJIEnv env, int objref, int bufref, int offset, int len, FeatureExpr ctx) {
// try {
// int fd = env.getIntField(objref, "fd").simplify(ctx).getValue().intValue();
// long off = env.getLongField(objref, "off").simplify(ctx).getValue();
//
// 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(ctx, bufref, j, One.valueOf(buf[i]));
// }
// env.setLongField(ctx, objref, "off", new One<>(fc.position()));
// return r;
//
// } else {
// env.throwException(ctx, "java.io.IOException", "read attempt on file opened for write access");
// return -1;
// }
//
// } else {
// if (env.getIntField(objref, "state").getValue().intValue() == FD_OPENED){ // backtracked
// reopen(env,objref, ctx);
// return read___3BII__I(env,objref,bufref,offset,len, ctx); // try again
// } else {
// env.throwException(ctx, "java.io.IOException", "read attempt on closed file");
// return -1;
// }
// }
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// return -1;
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// return -1;
// } catch (Exception e) {
// env.throwException(ctx, Exception.class.getName(), e.getMessage());
// return -1;
// }
// }
//
// @MJI
// public long skip__J__J (MJIEnv env, int objref, long nBytes, FeatureExpr ctx) {
// int fd = env.getIntField(objref, "fd").getValue().intValue();
// long off = env.getLongField(objref,"off").getValue();
//
// 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(ctx, objref, "off", new One<>(fc.position()));
// return r;
//
// } else {
// env.throwException(ctx, "java.io.IOException", "skip attempt on file opened for write access");
// return -1;
// }
//
// } else {
// env.throwException(ctx, "java.io.IOException", "skip attempt on closed file");
// return -1;
// }
//
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// return -1;
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// return -1;
// }
// }
//
// @MJI
// public void sync____ (MJIEnv env, int objref, FeatureExpr ctx) {
//// int fd = env.getIntField(objref, "fd").simplify(ctx).getValue().intValue();
// Conditional<Integer> fds = env.getIntField(objref, "fd").simplify(ctx);
//
// List<Integer> fdList = fds.toList();
//
// for (int fd : fdList) {
// try {
// Object fs = content.get(fd);
// if (fs != null) {
// if (fs instanceof FileOutputStream) {
// ((FileOutputStream) fs).flush();
// } else {
// // nothing
// }
//
// } else {
// env.throwException(ctx, "java.io.IOException", "sync attempt on closed file");
// }
//
// } catch (ArrayIndexOutOfBoundsException aobx) {
// env.throwException(ctx, "java.io.IOException", "file not open");
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// }
// }
// }
//
// @MJI
// public int available____I (MJIEnv env, int objref, FeatureExpr ctx) {
// try {
// int fd = env.getIntField(objref, "fd").simplify(ctx).getValue().intValue();
// long off = env.getLongField(objref,"off").simplify(ctx).getValue();
//
// 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(ctx, "java.io.IOException", "available() on file opened for write access");
// return -1;
// }
//
// } else {
// env.throwException(ctx, "java.io.IOException", "available() on closed file");
// return -1;
// }
//
// } catch (ArrayIndexOutOfBoundsException aobx){
// env.throwException(ctx, "java.io.IOException", "file not open");
// return -1;
// } catch (IOException iox) {
// env.throwException(ctx, "java.io.IOException", iox.getMessage());
// } catch (Exception e) {
// System.out.println(e.getMessage());
// }
// return -1;
//
// }
//}