Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7692bcb3 authored by John Wu's avatar John Wu Committed by Makoto Onuki
Browse files

[Ravenwood] Make Os.stat() family available

Add Ravenwood support for stat, lstat, and fstat.

Bug: 350811257
Test: atest RavenwoodRuntimeTest
Flag: TEST_ONLY (ravenwood)
Merged-in: I7c13021f539a38b3eb493ddbf3c04eadd5d8ef81
Change-Id: I7c13021f539a38b3eb493ddbf3c04eadd5d8ef81
parent 06a2deec
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ public final class Os {
        return RavenwoodRuntimeNative.lseek(fd, offset, whence);
    }


    public static FileDescriptor[] pipe2(int flags) throws ErrnoException {
        return RavenwoodRuntimeNative.pipe2(flags);
    }
@@ -42,4 +41,16 @@ public final class Os {
    public static int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException {
        return RavenwoodRuntimeNative.fcntlInt(fd, cmd, arg);
    }

    public static StructStat fstat(FileDescriptor fd) throws ErrnoException {
        return RavenwoodRuntimeNative.fstat(fd);
    }

    public static StructStat lstat(String path) throws ErrnoException {
        return RavenwoodRuntimeNative.lstat(path);
    }

    public static StructStat stat(String path) throws ErrnoException {
        return RavenwoodRuntimeNative.stat(path);
    }
}
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 android.system;

import libcore.util.Objects;

/**
 * File information returned by {@link Os#fstat}, {@link Os#lstat}, and {@link Os#stat}.
 * Corresponds to C's {@code struct stat} from {@code <stat.h>}.
 */
public final class StructStat {
    /** Device ID of device containing file. */
    public final long st_dev; /*dev_t*/

    /** File serial number (inode). */
    public final long st_ino; /*ino_t*/

    /** Mode (permissions) of file. */
    public final int st_mode; /*mode_t*/

    /** Number of hard links to the file. */
    public final long st_nlink; /*nlink_t*/

    /** User ID of file. */
    public final int st_uid; /*uid_t*/

    /** Group ID of file. */
    public final int st_gid; /*gid_t*/

    /** Device ID (if file is character or block special). */
    public final long st_rdev; /*dev_t*/

    /**
     * For regular files, the file size in bytes.
     * For symbolic links, the length in bytes of the pathname contained in the symbolic link.
     * For a shared memory object, the length in bytes.
     * For a typed memory object, the length in bytes.
     * For other file types, the use of this field is unspecified.
     */
    public final long st_size; /*off_t*/

    /** Seconds part of time of last access. */
    public final long st_atime; /*time_t*/

    /** StructTimespec with time of last access. */
    public final StructTimespec st_atim;

    /** Seconds part of time of last data modification. */
    public final long st_mtime; /*time_t*/

    /** StructTimespec with time of last modification. */
    public final StructTimespec st_mtim;

    /** Seconds part of time of last status change */
    public final long st_ctime; /*time_t*/

    /** StructTimespec with time of last status change. */
    public final StructTimespec st_ctim;

    /**
     * A file system-specific preferred I/O block size for this object.
     * For some file system types, this may vary from file to file.
     */
    public final long st_blksize; /*blksize_t*/

    /** Number of blocks allocated for this object. */
    public final long st_blocks; /*blkcnt_t*/

    /**
     * Constructs an instance with the given field values.
     */
    public StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid,
            long st_rdev, long st_size, long st_atime, long st_mtime, long st_ctime,
            long st_blksize, long st_blocks) {
        this(st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid,
                st_rdev, st_size, new StructTimespec(st_atime, 0L), new StructTimespec(st_mtime, 0L),
                new StructTimespec(st_ctime, 0L), st_blksize, st_blocks);
    }

    /**
     * Constructs an instance with the given field values.
     */
    public StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid,
            long st_rdev, long st_size, StructTimespec st_atim, StructTimespec st_mtim,
            StructTimespec st_ctim, long st_blksize, long st_blocks) {
        this.st_dev = st_dev;
        this.st_ino = st_ino;
        this.st_mode = st_mode;
        this.st_nlink = st_nlink;
        this.st_uid = st_uid;
        this.st_gid = st_gid;
        this.st_rdev = st_rdev;
        this.st_size = st_size;
        this.st_atime = st_atim.tv_sec;
        this.st_mtime = st_mtim.tv_sec;
        this.st_ctime = st_ctim.tv_sec;
        this.st_atim = st_atim;
        this.st_mtim = st_mtim;
        this.st_ctim = st_ctim;
        this.st_blksize = st_blksize;
        this.st_blocks = st_blocks;
    }

    @Override public String toString() {
        return Objects.toString(this);
    }
}
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 android.system;

import libcore.util.Objects;;

/**
 * Corresponds to C's {@code struct timespec} from {@code <time.h>}.
 */
public final class StructTimespec implements Comparable<StructTimespec> {
    /** Seconds part of time of last data modification. */
    public final long tv_sec; /*time_t*/

    /** Nanoseconds (values are [0, 999999999]). */
    public final long tv_nsec;

    public StructTimespec(long tv_sec, long tv_nsec) {
        this.tv_sec = tv_sec;
        this.tv_nsec = tv_nsec;
        if (tv_nsec < 0 || tv_nsec > 999_999_999) {
            throw new IllegalArgumentException(
                    "tv_nsec value " + tv_nsec + " is not in [0, 999999999]");
        }
    }

    @Override
    public int compareTo(StructTimespec other) {
        if (tv_sec > other.tv_sec) {
            return 1;
        }
        if (tv_sec < other.tv_sec) {
            return -1;
        }
        if (tv_nsec > other.tv_nsec) {
            return 1;
        }
        if (tv_nsec < other.tv_nsec) {
            return -1;
        }
        return 0;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        StructTimespec that = (StructTimespec) o;

        if (tv_sec != that.tv_sec) return false;
        return tv_nsec == that.tv_nsec;
    }

    @Override
    public int hashCode() {
        int result = (int) (tv_sec ^ (tv_sec >>> 32));
        result = 31 * result + (int) (tv_nsec ^ (tv_nsec >>> 32));
        return result;
    }

    @Override
    public String toString() {
        return Objects.toString(this);
    }
}
+23 −8
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.ravenwood.common;

import android.system.ErrnoException;
import android.system.StructStat;

import java.io.FileDescriptor;

/**
@@ -31,19 +34,25 @@ public class RavenwoodRuntimeNative {

    public static native void applyFreeFunction(long freeFunction, long nativePtr);

    public static native long nLseek(int fd, long offset, int whence);
    private static native long nLseek(int fd, long offset, int whence) throws ErrnoException;

    private static native int[] nPipe2(int flags) throws ErrnoException;

    private static native int nDup(int oldfd) throws ErrnoException;

    private static native int nFcntlInt(int fd, int cmd, int arg) throws ErrnoException;

    public static native int[] nPipe2(int flags);
    private static native StructStat nFstat(int fd) throws ErrnoException;

    public static native int nDup(int oldfd);
    public static native StructStat lstat(String path) throws ErrnoException;

    public static native int nFcntlInt(int fd, int cmd, int arg);
    public static native StructStat stat(String path) throws ErrnoException;

    public static long lseek(FileDescriptor fd, long offset, int whence) {
    public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
        return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
    }

    public static FileDescriptor[] pipe2(int flags) {
    public static FileDescriptor[] pipe2(int flags) throws ErrnoException {
        var fds = nPipe2(flags);
        var ret = new FileDescriptor[] {
                new FileDescriptor(),
@@ -55,7 +64,7 @@ public class RavenwoodRuntimeNative {
        return ret;
    }

    public static FileDescriptor dup(FileDescriptor fd) {
    public static FileDescriptor dup(FileDescriptor fd) throws ErrnoException {
        var fdInt = nDup(JvmWorkaround.getInstance().getFdInt(fd));

        var retFd = new java.io.FileDescriptor();
@@ -63,9 +72,15 @@ public class RavenwoodRuntimeNative {
        return retFd;
    }

    public static int fcntlInt(FileDescriptor fd, int cmd, int arg) {
    public static int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException {
        var fdInt = JvmWorkaround.getInstance().getFdInt(fd);

        return nFcntlInt(fdInt, cmd, arg);
    }

    public static StructStat fstat(FileDescriptor fd) throws ErrnoException {
        var fdInt = JvmWorkaround.getInstance().getFdInt(fd);

        return nFstat(fdInt);
    }
}
+85 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 libcore.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;

public final class Objects {
    private Objects() {}

    /**
     * Returns a string reporting the value of each declared field, via reflection.
     * Static and transient fields are automatically skipped. Produces output like
     * "SimpleClassName[integer=1234,string="hello",character='c',intArray=[1,2,3]]".
     */
    public static String toString(Object o) {
        Class<?> c = o.getClass();
        StringBuilder sb = new StringBuilder();
        sb.append(c.getSimpleName()).append('[');
        int i = 0;
        for (Field f : c.getDeclaredFields()) {
            if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) {
                continue;
            }
            f.setAccessible(true);
            try {
                Object value = f.get(o);

                if (i++ > 0) {
                    sb.append(',');
                }

                sb.append(f.getName());
                sb.append('=');

                if (value.getClass().isArray()) {
                    if (value.getClass() == boolean[].class) {
                        sb.append(Arrays.toString((boolean[]) value));
                    } else if (value.getClass() == byte[].class) {
                        sb.append(Arrays.toString((byte[]) value));
                    } else if (value.getClass() == char[].class) {
                        sb.append(Arrays.toString((char[]) value));
                    } else if (value.getClass() == double[].class) {
                        sb.append(Arrays.toString((double[]) value));
                    } else if (value.getClass() == float[].class) {
                        sb.append(Arrays.toString((float[]) value));
                    } else if (value.getClass() == int[].class) {
                        sb.append(Arrays.toString((int[]) value));
                    } else if (value.getClass() == long[].class) {
                        sb.append(Arrays.toString((long[]) value));
                    } else if (value.getClass() == short[].class) {
                        sb.append(Arrays.toString((short[]) value));
                    } else {
                        sb.append(Arrays.toString((Object[]) value));
                    }
                } else if (value.getClass() == Character.class) {
                    sb.append('\'').append(value).append('\'');
                } else if (value.getClass() == String.class) {
                    sb.append('"').append(value).append('"');
                } else {
                    sb.append(value);
                }
            } catch (IllegalAccessException unexpected) {
                throw new AssertionError(unexpected);
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
Loading