+ memset(addr,'/',1);
+ copyout(b,addr+1,b.length);
+ memset(addr+b.length+1,0,1);
+ return addr;
+ }
+
+ private int sys_chdir(int addr) throws ErrnoException, FaultException {
+ String path = normalizePath(cstring(addr));
+ FStat st = gs.stat(this,path);
+ if(st == null) return -ENOENT;
+ if(st.type() != FStat.S_IFDIR) return -ENOTDIR;
+ cwd = path;
+ return 0;
+ }
+
+ private int sys_getdents(int fdn, int addr, int count, int seekptr) throws FaultException, ErrnoException {
+ count = Math.min(count,MAX_CHUNK);
+ if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+ if(fds[fdn] == null) return -EBADFD;
+ byte[] buf = byteBuf(count);
+ int n = fds[fdn].getdents(buf,0,count);
+ copyout(buf,addr,n);
+ return n;
+ }
+
+ static class SocketFD extends FD {
+ public static final int TYPE_STREAM = 0;
+ public static final int TYPE_DGRAM = 1;
+ public static final int LISTEN = 2;
+ public int type() { return flags & 1; }
+ public boolean listen() { return (flags & 2) != 0; }
+
+ int flags;
+ int options;
+
+ Socket s;
+ ServerSocket ss;
+ DatagramSocket ds;
+
+ InetAddress bindAddr;
+ int bindPort = -1;
+ InetAddress connectAddr;
+ int connectPort = -1;
+
+ DatagramPacket dp;
+ InputStream is;
+ OutputStream os;
+
+ private static final byte[] EMPTY = new byte[0];
+ public SocketFD(int type) {
+ flags = type;
+ if(type == TYPE_DGRAM)
+ dp = new DatagramPacket(EMPTY,0);
+ }
+
+ public void setOptions() {
+ try {
+ if(s != null && type() == TYPE_STREAM && !listen()) {
+ Platform.socketSetKeepAlive(s,(options & SO_KEEPALIVE) != 0);
+ }
+ } catch(SocketException e) {
+ if(STDERR_DIAG) e.printStackTrace();
+ }
+ }
+
+ public void _close() {
+ try {
+ if(s != null) s.close();
+ if(ss != null) ss.close();
+ if(ds != null) ds.close();
+ } catch(IOException e) {
+ /* ignore */
+ }
+ }
+
+ public int read(byte[] a, int off, int length) throws ErrnoException {
+ if(type() == TYPE_DGRAM) return recvfrom(a,off,length,null,null);
+ if(is == null) throw new ErrnoException(EPIPE);
+ try {
+ int n = is.read(a,off,length);
+ return n < 0 ? 0 : n;
+ } catch(IOException e) {
+ throw new ErrnoException(EIO);
+ }
+ }
+
+ public int recvfrom(byte[] a, int off, int length, InetAddress[] sockAddr, int[] port) throws ErrnoException {
+ if(type() == TYPE_STREAM) return read(a,off,length);
+
+ if(off != 0) throw new IllegalArgumentException("off must be 0");
+ dp.setData(a);
+ dp.setLength(length);
+ try {
+ if(ds == null) ds = new DatagramSocket();
+ ds.receive(dp);
+ } catch(IOException e) {
+ if(STDERR_DIAG) e.printStackTrace();
+ throw new ErrnoException(EIO);
+ }
+ if(sockAddr != null) {
+ sockAddr[0] = dp.getAddress();
+ port[0] = dp.getPort();
+ }
+ return dp.getLength();
+ }
+
+ public int write(byte[] a, int off, int length) throws ErrnoException {
+ if(type() == TYPE_DGRAM) return sendto(a,off,length,null,-1);
+
+ if(os == null) throw new ErrnoException(EPIPE);
+ try {
+ os.write(a,off,length);
+ return length;
+ } catch(IOException e) {
+ throw new ErrnoException(EIO);
+ }
+ }
+
+ public int sendto(byte[] a, int off, int length, InetAddress destAddr, int destPort) throws ErrnoException {
+ if(off != 0) throw new IllegalArgumentException("off must be 0");
+ if(type() == TYPE_STREAM) return write(a,off,length);
+
+ if(destAddr == null) {
+ destAddr = connectAddr;
+ destPort = connectPort;
+
+ if(destAddr == null) throw new ErrnoException(ENOTCONN);
+ }
+
+ dp.setAddress(destAddr);
+ dp.setPort(destPort);
+ dp.setData(a);
+ dp.setLength(length);
+
+ try {
+ if(ds == null) ds = new DatagramSocket();
+ ds.send(dp);
+ } catch(IOException e) {
+ if(STDERR_DIAG) e.printStackTrace();
+ if("Network is unreachable".equals(e.getMessage())) throw new ErrnoException(EHOSTUNREACH);
+ throw new ErrnoException(EIO);
+ }
+ return dp.getLength();
+ }
+
+ public int flags() { return O_RDWR; }
+ public FStat _fstat() { return new SocketFStat(); }
+ }
+
+ private int sys_socket(int domain, int type, int proto) {
+ if(domain != AF_INET || (type != SOCK_STREAM && type != SOCK_DGRAM)) return -EPROTONOSUPPORT;
+ return addFD(new SocketFD(type == SOCK_STREAM ? SocketFD.TYPE_STREAM : SocketFD.TYPE_DGRAM));
+ }
+
+ private SocketFD getSocketFD(int fdn) throws ErrnoException {
+ if(fdn < 0 || fdn >= OPEN_MAX) throw new ErrnoException(EBADFD);
+ if(fds[fdn] == null) throw new ErrnoException(EBADFD);
+ if(!(fds[fdn] instanceof SocketFD)) throw new ErrnoException(ENOTSOCK);
+
+ return (SocketFD) fds[fdn];
+ }
+
+ private int sys_connect(int fdn, int addr, int namelen) throws ErrnoException, FaultException {
+ SocketFD fd = getSocketFD(fdn);
+
+ if(fd.type() == SocketFD.TYPE_STREAM && (fd.s != null || fd.ss != null)) return -EISCONN;
+ int word1 = memRead(addr);
+ if( ((word1 >>> 16)&0xff) != AF_INET) return -EAFNOSUPPORT;
+ int port = word1 & 0xffff;
+ byte[] ip = new byte[4];
+ copyin(addr+4,ip,4);
+
+ InetAddress inetAddr;