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

Commit df2e7b88 authored by Corina Grigoras's avatar Corina Grigoras Committed by Android (Google) Code Review
Browse files

Merge "Revert "Restore file truncation where expected."" into sc-dev

parents 8f28e577 3fcb12e2
Loading
Loading
Loading
Loading
+22 −15
Original line number Diff line number Diff line
@@ -1885,9 +1885,9 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
     * in {@link android.provider.MediaStore.MediaColumns}.</p>
     *
     * @param uri The URI whose file is to be opened.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode Access mode for the file.  May be "r" for read-only access,
     * "rw" for read and write access, or "rwt" for read and write access
     * that truncates any existing file.
     *
     * @return Returns a new ParcelFileDescriptor which you can use to access
     * the file.
@@ -1948,9 +1948,10 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
     * in {@link android.provider.MediaStore.MediaColumns}.</p>
     *
     * @param uri The URI whose file is to be opened.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode Access mode for the file. May be "r" for read-only access,
     *            "w" for write-only access, "rw" for read and write access, or
     *            "rwt" for read and write access that truncates any existing
     *            file.
     * @param signal A signal to cancel the operation in progress, or
     *            {@code null} if none. For example, if you are downloading a
     *            file from the network to service a "rw" mode request, you
@@ -2010,9 +2011,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
     * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
     *
     * @param uri The URI whose file is to be opened.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode Access mode for the file.  May be "r" for read-only access,
     * "w" for write-only access (erasing whatever data is currently in
     * the file), "wa" for write-only access to append to any existing data,
     * "rw" for read and write access on any existing data, and "rwt" for read
     * and write access that truncates any existing file.
     *
     * @return Returns a new AssetFileDescriptor which you can use to access
     * the file.
@@ -2065,9 +2068,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
     * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
     *
     * @param uri The URI whose file is to be opened.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode Access mode for the file.  May be "r" for read-only access,
     * "w" for write-only access (erasing whatever data is currently in
     * the file), "wa" for write-only access to append to any existing data,
     * "rw" for read and write access on any existing data, and "rwt" for read
     * and write access that truncates any existing file.
     * @param signal A signal to cancel the operation in progress, or
     *            {@code null} if none. For example, if you are downloading a
     *            file from the network to service a "rw" mode request, you
@@ -2098,9 +2103,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
     * by looking up a column named "_data" at the given URI.
     *
     * @param uri The URI to be opened.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode The file mode.  May be "r" for read-only access,
     * "w" for write-only access (erasing whatever data is currently in
     * the file), "wa" for write-only access to append to any existing data,
     * "rw" for read and write access on any existing data, and "rwt" for read
     * and write access that truncates any existing file.
     *
     * @return Returns a new ParcelFileDescriptor that can be used by the
     * client to access the file.
+13 −73
Original line number Diff line number Diff line
@@ -63,9 +63,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Int64Ref;
import android.system.Os;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
@@ -78,10 +76,8 @@ import com.android.internal.util.MimeIconUtils;
import dalvik.system.CloseGuard;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -868,20 +864,6 @@ public abstract class ContentResolver implements ContentInterface {
        return wrap((ContentInterface) wrapped);
    }

    /**
     * Offer to locally truncate the given file when opened using the write-only
     * mode. This is typically used to preserve legacy compatibility behavior.
     */
    private static void maybeTruncate(FileDescriptor fd, String mode) throws FileNotFoundException {
        if ("w".equals(mode)) {
            try {
                Os.ftruncate(fd, 0);
            } catch (ErrnoException e) {
                throw new FileNotFoundException("Failed to truncate: " + e.getMessage());
            }
        }
    }

    /** @hide */
    @SuppressWarnings("HiddenAbstractMethod")
    @UnsupportedAppUsage
@@ -1543,20 +1525,8 @@ public abstract class ContentResolver implements ContentInterface {
    }

    /**
     * Open a stream on to the content associated with a content URI.  If there
     * is no data associated with the URI, FileNotFoundException is thrown.
     *
     * <h5>Accepts the following URI schemes:</h5>
     * <ul>
     * <li>content ({@link #SCHEME_CONTENT})</li>
     * <li>file ({@link #SCHEME_FILE})</li>
     * </ul>
     *
     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
     * on these schemes.
     *
     * <p>This method behaves like {@link FileOutputStream} and automatically
     * truncates any existing contents.
     * Synonym for {@link #openOutputStream(Uri, String)
     * openOutputStream(uri, "w")}.
     *
     * @param uri The desired URI.
     * @return an OutputStream or {@code null} if the provider recently crashed.
@@ -1564,16 +1534,7 @@ public abstract class ContentResolver implements ContentInterface {
     */
    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
            throws FileNotFoundException {
        AssetFileDescriptor fd = openAssetFileDescriptor(uri, "w", null);
        if (fd == null) return null;
        try {
            final FileOutputStream res = fd.createOutputStream();
            // Unconditionally truncate to mirror FileOutputStream behavior
            maybeTruncate(res.getFD(), "w");
            return res;
        } catch (IOException e) {
            throw new FileNotFoundException("Unable to create stream");
        }
        return openOutputStream(uri, "w");
    }

    /**
@@ -1590,9 +1551,7 @@ public abstract class ContentResolver implements ContentInterface {
     * on these schemes.
     *
     * @param uri The desired URI.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode May be "w", "wa", "rw", or "rwt".
     * @return an OutputStream or {@code null} if the provider recently crashed.
     * @throws FileNotFoundException if the provided URI could not be opened.
     * @see #openAssetFileDescriptor(Uri, String)
@@ -1600,14 +1559,8 @@ public abstract class ContentResolver implements ContentInterface {
    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
            throws FileNotFoundException {
        AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
        if (fd == null) return null;
        try {
            final FileOutputStream res = fd.createOutputStream();
            // Preserve legacy behavior by offering to truncate
            if (mTargetSdkVersion < Build.VERSION_CODES.Q) {
                maybeTruncate(res.getFD(), mode);
            }
            return res;
            return fd != null ? fd.createOutputStream() : null;
        } catch (IOException e) {
            throw new FileNotFoundException("Unable to create stream");
        }
@@ -1654,9 +1607,8 @@ public abstract class ContentResolver implements ContentInterface {
     * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
     *
     * @param uri The desired URI to open.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode The file mode to use, as per {@link ContentProvider#openFile
     * ContentProvider.openFile}.
     * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
     * provider recently crashed. You own this descriptor and are responsible for closing it
     * when done.
@@ -1698,9 +1650,8 @@ public abstract class ContentResolver implements ContentInterface {
     * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
     *
     * @param uri The desired URI to open.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode The file mode to use, as per {@link ContentProvider#openFile
     * ContentProvider.openFile}.
     * @param cancellationSignal A signal to cancel the operation in progress,
     *         or null if none. If the operation is canceled, then
     *         {@link OperationCanceledException} will be thrown.
@@ -1793,9 +1744,8 @@ public abstract class ContentResolver implements ContentInterface {
     * from any built-in data conversion that a provider implements.
     *
     * @param uri The desired URI to open.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
     * ContentProvider.openAssetFile}.
     * @return Returns a new ParcelFileDescriptor pointing to the file or {@code null} if the
     * provider recently crashed. You own this descriptor and are responsible for closing it
     * when done.
@@ -1848,9 +1798,8 @@ public abstract class ContentResolver implements ContentInterface {
     * from any built-in data conversion that a provider implements.
     *
     * @param uri The desired URI to open.
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt". See
     *            {@link ParcelFileDescriptor#parseMode} for more details.
     * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile
     * ContentProvider.openAssetFile}.
     * @param cancellationSignal A signal to cancel the operation in progress, or null if
     *            none. If the operation is canceled, then
     *            {@link OperationCanceledException} will be thrown.
@@ -1886,10 +1835,6 @@ public abstract class ContentResolver implements ContentInterface {
        } else if (SCHEME_FILE.equals(scheme)) {
            ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                    new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
            // Preserve legacy behavior by offering to truncate
            if (mTargetSdkVersion < Build.VERSION_CODES.Q) {
                maybeTruncate(pfd.getFileDescriptor(), mode);
            }
            return new AssetFileDescriptor(pfd, 0, -1);
        } else {
            if ("r".equals(mode)) {
@@ -1947,11 +1892,6 @@ public abstract class ContentResolver implements ContentInterface {
                    // ParcelFileDescriptorInner do that when it is closed.
                    stableProvider = null;

                    // Preserve legacy behavior by offering to truncate
                    if (mTargetSdkVersion < Build.VERSION_CODES.Q) {
                        maybeTruncate(pfd.getFileDescriptor(), mode);
                    }

                    return new AssetFileDescriptor(pfd, fd.getStartOffset(),
                            fd.getDeclaredLength());

+9 −49
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import static android.system.OsConstants.S_ISLNK;
import static android.system.OsConstants.S_ISREG;
import static android.system.OsConstants.S_IWOTH;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -64,8 +63,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.DatagramSocket;
import java.net.Socket;
import java.nio.ByteOrder;
@@ -113,20 +110,6 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {

    private final CloseGuard mGuard = CloseGuard.get();

    /** @hide */
    @IntDef(prefix = {"MODE_"}, value = {
            MODE_WORLD_READABLE,
            MODE_WORLD_WRITEABLE,
            MODE_READ_ONLY,
            MODE_WRITE_ONLY,
            MODE_READ_WRITE,
            MODE_CREATE,
            MODE_TRUNCATE,
            MODE_APPEND,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Mode { }

    /**
     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and
     * this file doesn't already exist, then create the file with permissions
@@ -244,8 +227,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
     *             be opened with the requested mode.
     * @see #parseMode(String)
     */
    public static ParcelFileDescriptor open(File file, @Mode int mode)
            throws FileNotFoundException {
    public static ParcelFileDescriptor open(File file, int mode) throws FileNotFoundException {
        final FileDescriptor fd = openInternal(file, mode);
        if (fd == null) return null;

@@ -277,7 +259,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
    // We can't accept a generic Executor here, since we need to use
    // MessageQueue.addOnFileDescriptorEventListener()
    @SuppressLint("ExecutorRegistration")
    public static ParcelFileDescriptor open(File file, @Mode int mode, Handler handler,
    public static ParcelFileDescriptor open(File file, int mode, Handler handler,
            final OnCloseListener listener) throws IOException {
        if (handler == null) {
            throw new IllegalArgumentException("Handler must not be null");
@@ -348,8 +330,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
        return pfd;
    }

    private static FileDescriptor openInternal(File file, @Mode int mode)
            throws FileNotFoundException {
    private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
        final int flags = FileUtils.translateModePfdToPosix(mode) | ifAtLeastQ(O_CLOEXEC);

        int realMode = S_IRWXU | S_IRWXG;
@@ -642,36 +623,15 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
    }

    /**
     * Converts a string representing a file mode, such as "rw", into a bitmask
     * suitable for use with {@link #open}.
     * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
     * with {@link #open}.
     * <p>
     * The argument must define at least one of the following base access modes:
     * <ul>
     * <li>"r" indicates the file should be opened in read-only mode, equivalent
     * to {@link OsConstants#O_RDONLY}.
     * <li>"w" indicates the file should be opened in write-only mode,
     * equivalent to {@link OsConstants#O_WRONLY}.
     * <li>"rw" indicates the file should be opened in read-write mode,
     * equivalent to {@link OsConstants#O_RDWR}.
     * </ul>
     * In addition to a base access mode, the following additional modes may
     * requested:
     * <ul>
     * <li>"a" indicates the file should be opened in append mode, equivalent to
     * {@link OsConstants#O_APPEND}. Before each write, the file offset is
     * positioned at the end of the file.
     * <li>"t" indicates the file should be opened in truncate mode, equivalent
     * to {@link OsConstants#O_TRUNC}. If the file already exists and is a
     * regular file and is opened for writing, it will be truncated to length 0.
     * </ul>
     *
     * @param mode The string representation of the file mode. Can be "r", "w",
     *            "wt", "wa", "rw" or "rwt".
     * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
     *             or "rwt".
     * @return A bitmask representing the given file mode.
     * @throws IllegalArgumentException if the given string does not match a
     *             known file mode.
     * @throws IllegalArgumentException if the given string does not match a known file mode.
     */
    public static @Mode int parseMode(String mode) {
    public static int parseMode(String mode) {
        return FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode));
    }