All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.unidbg.ios.file.DirectoryFileIO Maven / Gradle / Ivy

The newest version!
package com.github.unidbg.ios.file;

import com.github.unidbg.Emulator;
import com.github.unidbg.arm.ARM;
import com.github.unidbg.file.UnidbgFileFilter;
import com.github.unidbg.file.ios.BaseDarwinFileIO;
import com.github.unidbg.file.ios.StatStructure;
import com.github.unidbg.ios.struct.Dirent;
import com.github.unidbg.ios.struct.kernel.StatFS;
import com.github.unidbg.pointer.UnidbgPointer;
import com.github.unidbg.unix.IO;
import com.sun.jna.Pointer;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class DirectoryFileIO extends BaseDarwinFileIO {

    public static class DirectoryEntry {
        private final boolean isFile;
        private final String name;
        public DirectoryEntry(boolean isFile, String name) {
            this.isFile = isFile;
            this.name = name;
        }
    }

    private static DirectoryEntry[] createEntries(File dir) {
        List list = new ArrayList<>();
        File[] files = dir.listFiles(new UnidbgFileFilter());
        if (files != null) {
            Arrays.sort(files);
            for (File file : files) {
                list.add(new DirectoryEntry(file.isFile(), file.getName()));
            }
        }
        return list.toArray(new DirectoryEntry[0]);
    }

    private final String path;

    private final List entries;

    private final File dir;

    public DirectoryFileIO(int oflags, String path, File dir) {
        this(oflags, path, dir, createEntries(dir));
    }

    public DirectoryFileIO(int oflags, String path, DirectoryEntry... entries) {
        this(oflags, path, null, entries);
    }

    public DirectoryFileIO(int oflags, String path, File dir, DirectoryEntry... entries) {
        super(oflags);

        this.path = path;
        this.dir = dir;

        this.entries = new ArrayList<>();
        this.entries.add(new DirectoryEntry(false, "."));
        this.entries.add(new DirectoryEntry(false, ".."));
        if (entries != null) {
            Collections.addAll(this.entries, entries);
        }
    }

    @Override
    public int fstatfs(StatFS statFS) {
        return 0;
    }

    @Override
    public int fstat(Emulator emulator, StatStructure stat) {
        stat.st_dev = 1;
        stat.st_mode = IO.S_IFDIR | 0x777;
        stat.setSize(0);
        stat.st_blksize = 0;
        stat.st_ino = 7;
        stat.pack();
        return 0;
    }

    @Override
    public void close() {
    }

    @Override
    public String toString() {
        return path;
    }

    @Override
    public int fcntl(Emulator emulator, int cmd, long arg) {
        if (cmd == F_GETPATH) {
            UnidbgPointer pointer = UnidbgPointer.pointer(emulator, arg);
            if (pointer != null) {
                pointer.setString(0, getPath());
            }
            return 0;
        }

        return super.fcntl(emulator, cmd, arg);
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public int getdirentries64(Pointer buf, int bufSize) {
        int offset = 0;
        for (Iterator iterator = this.entries.iterator(); iterator.hasNext(); ) {
            DirectoryFileIO.DirectoryEntry entry = iterator.next();
            byte[] data = entry.name.getBytes(StandardCharsets.UTF_8);
            long d_reclen = ARM.alignSize(data.length + 24, 8);

            if (offset + d_reclen >= bufSize) {
                break;
            }

            Dirent dirent = new Dirent(buf.share(offset));
            dirent.d_fileno = 1;
            dirent.d_reclen = (short) d_reclen;
            dirent.d_type = entry.isFile ? Dirent.DT_REG : Dirent.DT_DIR;
            dirent.d_namlen = (short) (data.length);
            dirent.d_name = Arrays.copyOf(data, data.length + 1);
            dirent.pack();
            offset += d_reclen;

            iterator.remove();
        }

        return offset;
    }

    @Override
    public int listxattr(Pointer namebuf, int size, int options) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", options=0x" + Integer.toHexString(options));
        }
        return listxattr(dir, namebuf, size);
    }

    @Override
    public int removexattr(String name) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", name=" + name);
        }
        return removexattr(dir, name);
    }

    @Override
    public int setxattr(String name, byte[] data) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", name=" + name);
        }
        return setxattr(dir, name, data);
    }

    @Override
    public int getxattr(Emulator emulator, String name, Pointer value, int size) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", name=" + name);
        }
        return getxattr(emulator, dir, name, value, size);
    }

    @Override
    public int chmod(int mode) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", mode=0x" + Integer.toHexString(mode));
        }
        return chmod(dir, mode);
    }

    @Override
    public int chown(int uid, int gid) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", uid=" + uid + ", gid=" + gid);
        }
        return chown(dir, uid, gid);
    }

    @Override
    public int chflags(int flags) {
        if (dir == null) {
            throw new UnsupportedOperationException("path=" + path + ", flags=0x" + Integer.toHexString(flags));
        }
        return chflags(dir, flags);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy