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

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

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

import com.alibaba.fastjson.JSON;
import com.github.unidbg.Emulator;
import com.github.unidbg.file.BaseFileIO;
import com.github.unidbg.file.UnidbgFileFilter;
import com.github.unidbg.ios.file.DirectoryFileIO;
import com.github.unidbg.ios.struct.attr.AttrList;
import com.github.unidbg.ios.struct.attr.AttrReference;
import com.github.unidbg.ios.struct.attr.AttributeSet;
import com.github.unidbg.ios.struct.attr.Dev;
import com.github.unidbg.ios.struct.attr.FinderInfo;
import com.github.unidbg.ios.struct.attr.Fsid;
import com.github.unidbg.ios.struct.attr.ObjId;
import com.github.unidbg.ios.struct.attr.ObjType;
import com.github.unidbg.ios.struct.attr.UserAccess;
import com.github.unidbg.ios.struct.kernel.StatFS;
import com.github.unidbg.pointer.UnidbgStructure;
import com.github.unidbg.unix.UnixEmulator;
import com.github.unidbg.unix.struct.TimeSpec32;
import com.sun.jna.Pointer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public abstract class BaseDarwinFileIO extends BaseFileIO implements DarwinFileIO {

    private static final Log log = LogFactory.getLog(BaseDarwinFileIO.class);

    public static File createAttrFile(File dest) {
        if (!dest.exists()) {
            throw new IllegalStateException("dest=" + dest);
        }

        File file;
        if (dest.isDirectory()) {
            file = new File(dest, UnidbgFileFilter.UNIDBG_PREFIX + ".json");
        } else {
            file = new File(dest.getParentFile(), UnidbgFileFilter.UNIDBG_PREFIX + "_" + dest.getName() + ".json");
        }
        return file;
    }

    public BaseDarwinFileIO(int oflags) {
        super(oflags);
    }

    public int fstat(Emulator emulator, StatStructure stat) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    private int protectionClass;

    @Override
    public int fcntl(Emulator emulator, int cmd, long arg) {
        if (cmd == F_NOCACHE) {
            return 0;
        }
        if (cmd == F_SETLK) {
            return 0;
        }
        if (cmd == F_SETLKW) {
            return 0;
        }
        if (cmd == F_SETPROTECTIONCLASS) {
            protectionClass = (int) arg;
            return 0;
        }
        if (cmd == F_GETPROTECTIONCLASS) {
            return protectionClass;
        }
        if(cmd == F_SINGLE_WRITER) {
            return 0;
        }
        if (cmd == F_PREALLOCATE) {
            return 0;
        }

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

    public int fstatfs(StatFS statFS) {
        throw new UnsupportedOperationException(getClass().getName() + " path=" + getPath());
    }

    @Override
    public int getattrlist(AttrList attrList, Pointer attrBuf, int attrBufSize) {
        if (attrList.bitmapcount != ATTR_BIT_MAP_COUNT) {
            throw new UnsupportedOperationException("bitmapcount=" + attrList.bitmapcount);
        }
        AttributeSet attributeSet = attrList.attributeSet;
        Pointer pointer = attrBuf.share(4);
        List list = new ArrayList<>();
        List attrReferenceList = new ArrayList<>();
        AttributeSet returnedAttributeSet = null;
        if ((attributeSet.commonattr & ATTR_CMN_RETURNED_ATTRS) != 0) {
            returnedAttributeSet = new AttributeSet(pointer);
            pointer = pointer.share(returnedAttributeSet.size());
            list.add(returnedAttributeSet);
            attributeSet.commonattr &= ~ATTR_CMN_RETURNED_ATTRS;
        }
        if((attributeSet.commonattr & ATTR_CMN_NAME) != 0) {
            String name = FilenameUtils.getName(getPath());
            byte[] bytes = name.getBytes(StandardCharsets.UTF_8);
            AttrReference attrReference = new AttrReference(pointer, bytes);
            attrReferenceList.add(attrReference);
            pointer = pointer.share(attrReference.size());
            list.add(attrReference);
            attributeSet.commonattr &= ~ATTR_CMN_NAME;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_NAME;
            }
        }
        if((attributeSet.commonattr & ATTR_CMN_DEVID) != 0) {
            Dev dev = new Dev(pointer);
            dev.dev = 1;
            pointer = pointer.share(dev.size());
            list.add(dev);
            attributeSet.commonattr &= ~ATTR_CMN_DEVID;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_DEVID;
            }
        }
        if((attributeSet.commonattr & ATTR_CMN_FSID) != 0) {
            Fsid fsid = new Fsid(pointer);
            fsid.val[0] = 0;
            fsid.val[1] = 0;
            pointer = pointer.share(fsid.size());
            list.add(fsid);
            attributeSet.commonattr &= ~ATTR_CMN_FSID;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_FSID;
            }
        }
        if((attributeSet.commonattr & ATTR_CMN_OBJTYPE) != 0) {
            ObjType objType = new ObjType(pointer);
            objType.type = this instanceof DirectoryFileIO ? vtype.VDIR.ordinal() : vtype.VREG.ordinal();
            pointer = pointer.share(objType.size());
            list.add(objType);
            attributeSet.commonattr &= ~ATTR_CMN_OBJTYPE;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_OBJTYPE;
            }
        }
        if((attributeSet.commonattr & ATTR_CMN_OBJID) != 0) {
            ObjId objId = new ObjId(pointer);
            objId.fid_objno = 0;
            objId.fid_generation = 0;
            pointer = pointer.share(objId.size());
            list.add(objId);
            attributeSet.commonattr &= ~ATTR_CMN_OBJID;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_OBJID;
            }
        }
        if((attributeSet.commonattr & ATTR_CMN_CRTIME) != 0) {
            TimeSpec32 timeSpec = new TimeSpec32(pointer);
            pointer = pointer.share(timeSpec.size());
            list.add(timeSpec);
            attributeSet.commonattr &= ~ATTR_CMN_CRTIME;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_CRTIME;
            }
        }
        if ((attributeSet.commonattr & ATTR_CMN_FNDRINFO) != 0) {
            FinderInfo finderInfo = new FinderInfo(pointer);
            pointer = pointer.share(finderInfo.size());
            list.add(finderInfo);
            attributeSet.commonattr &= ~ATTR_CMN_FNDRINFO;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_FNDRINFO;
            }
        }
        if ((attributeSet.commonattr & ATTR_CMN_USERACCESS) != 0) {
            UserAccess userAccess = new UserAccess(pointer);
            userAccess.mode = X_OK | W_OK | R_OK;
//            pointer = pointer.share(userAccess.size());
            list.add(userAccess);
            attributeSet.commonattr &= ~ATTR_CMN_USERACCESS;
            if (returnedAttributeSet != null) {
                returnedAttributeSet.commonattr |= ATTR_CMN_USERACCESS;
            }
        }
        if (attributeSet.commonattr != 0 || attributeSet.volattr != 0 ||
                attributeSet.dirattr != 0 || attributeSet.fileattr != 0 ||
                attributeSet.forkattr != 0) {
            if (returnedAttributeSet == null) {
                return -1;
            }
        }
        int len = 0;
        for (UnidbgStructure structure : list) {
            int size = structure.size();
            len += size;
            structure.pack();

            for (AttrReference attrReference : attrReferenceList) {
                attrReference.check(structure, size);
            }
        }
        attrBuf.setInt(0, len + 4);

        for (AttrReference attrReference : attrReferenceList) {
            pointer = attrBuf.share(attrReference.attr_dataoffset + 4);
            attrReference.writeAttr(pointer);
        }

        return 0;
    }

    @Override
    public int setattrlist(AttrList attrList, Pointer attrBuf, int attrBufSize) {
        if (attrList.bitmapcount != ATTR_BIT_MAP_COUNT) {
            throw new UnsupportedOperationException("bitmapcount=" + attrList.bitmapcount);
        }
        AttributeSet attributeSet = attrList.attributeSet;
        Pointer pointer = attrBuf.share(4);
        if((attributeSet.commonattr & ATTR_CMN_CRTIME) != 0) {
            TimeSpec32 timeSpec = new TimeSpec32(pointer);
            pointer = pointer.share(timeSpec.size());
            if (log.isDebugEnabled()) {
                log.debug("setattrlist timeSpec=" + timeSpec + ", pointer=" + pointer);
            }
            attributeSet.commonattr &= ~ATTR_CMN_CRTIME;
        }
        if((attributeSet.commonattr & ATTR_CMN_MODTIME) != 0) {
            TimeSpec32 timeSpec = new TimeSpec32(pointer);
            pointer = pointer.share(timeSpec.size());
            if (log.isDebugEnabled()) {
                log.debug("setattrlist timeSpec=" + timeSpec + ", pointer=" + pointer);
            }
            attributeSet.commonattr &= ~ATTR_CMN_MODTIME;
        }
        if ((attributeSet.commonattr & ATTR_CMN_FNDRINFO) != 0) {
            FinderInfo finderInfo = new FinderInfo(pointer);
            pointer = pointer.share(finderInfo.size());
            if (log.isDebugEnabled()) {
                log.debug("setattrlist finderInfo=" + finderInfo + ", pointer=" + pointer);
            }
            attributeSet.commonattr &= ~ATTR_CMN_FNDRINFO;
        }
        if (attributeSet.commonattr != 0 || attributeSet.volattr != 0 ||
                attributeSet.dirattr != 0 || attributeSet.fileattr != 0 ||
                attributeSet.forkattr != 0) {
            return -1;
        }
        return 0;
    }

    @Override
    public int getdirentries64(Pointer buf, int bufSize) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int listxattr(Pointer namebuf, int size, int options) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int removexattr(String name) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int setxattr(String name, byte[] data) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int getxattr(Emulator emulator, String name, Pointer value, int size) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int chown(int uid, int gid) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int chmod(int mode) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    @Override
    public int chflags(int flags) {
        throw new UnsupportedOperationException(getClass().getName());
    }

    protected final int chflags(File dest, int flags) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null) {
                attr = new DarwinFileAttr();
            }
            attr.flags = flags;
            File file = createAttrFile(dest);
            FileUtils.writeStringToFile(file, JSON.toJSONString(attr), StandardCharsets.UTF_8);
            return 0;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final int chmod(File dest, int mode) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null) {
                attr = new DarwinFileAttr();
            }
            attr.mode = mode;
            File file = createAttrFile(dest);
            FileUtils.writeStringToFile(file, JSON.toJSONString(attr), StandardCharsets.UTF_8);
            return 0;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final int chown(File dest, int uid, int gid) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null) {
                attr = new DarwinFileAttr();
            }
            attr.uid = uid;
            attr.gid = gid;
            File file = createAttrFile(dest);
            FileUtils.writeStringToFile(file, JSON.toJSONString(attr), StandardCharsets.UTF_8);
            return 0;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final DarwinFileAttr loadAttr(File dest) throws IOException {
        File file = createAttrFile(dest);
        if (file.exists()) {
            return JSON.parseObject(FileUtils.readFileToString(file, StandardCharsets.UTF_8), DarwinFileAttr.class);
        } else {
            return null;
        }
    }

    protected final int listxattr(File dest, Pointer namebuf, int size) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null || attr.xattr == null) {
                return 0;
            }
            int ret = 0;
            Pointer buffer = namebuf;
            for (String name : attr.xattr.keySet()) {
                byte[] data = name.getBytes(StandardCharsets.UTF_8);
                ret += (data.length + 1);

                if (buffer != null && ret <= size) {
                    buffer.write(0, Arrays.copyOf(data, data.length + 1), 0, data.length + 1);
                    buffer = buffer.share(data.length + 1);
                }
            }
            return ret;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final int getxattr(Emulator emulator, File dest, String name, Pointer value, int size) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            byte[] data = attr == null || attr.xattr == null ? null : attr.xattr.get(name);
            if (data == null) {
                emulator.getMemory().setErrno(UnixEmulator.ENOATTR);
                return -1;
            }
            if (value == null) {
                return data.length;
            } else if (size >= data.length) {
                value.write(0, data, 0, data.length);
                return data.length;
            } else {
                value.write(0, data, 0, size);
                return size;
            }
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final int setxattr(File dest, String name, byte[] data) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null) {
                attr = new DarwinFileAttr();
            }
            if (attr.xattr == null) {
                attr.xattr = new HashMap<>();
            }
            attr.xattr.put(name, data);
            File file = createAttrFile(dest);
            FileUtils.writeStringToFile(file, JSON.toJSONString(attr), StandardCharsets.UTF_8);
            return 0;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected final int removexattr(File dest, String name) {
        try {
            DarwinFileAttr attr = loadAttr(dest);
            if (attr == null) {
                attr = new DarwinFileAttr();
            }
            if (attr.xattr == null) {
                attr.xattr = new HashMap<>();
            }
            attr.xattr.remove(name);
            File file = createAttrFile(dest);
            FileUtils.writeStringToFile(file, JSON.toJSONString(attr), StandardCharsets.UTF_8);
            return 0;
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    protected void setFlags(long arg) {
        if ((IOConstants.O_APPEND & arg) != 0) {
            oflags |= IOConstants.O_APPEND;
        }
        if ((IOConstants.O_RDWR & arg) != 0) {
            oflags |= IOConstants.O_RDWR;
        }
        if ((IOConstants.O_NONBLOCK & arg) != 0) {
            oflags |= IOConstants.O_NONBLOCK;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy