1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.system;
18 
19 import java.io.IOException;
20 import java.net.SocketException;
21 import libcore.io.Libcore;
22 import libcore.util.NonNull;
23 
24 /**
25  * A checked exception thrown when {@link Os} methods fail. This exception contains the native
26  * errno value, for comparison against the constants in {@link OsConstants}, should sophisticated
27  * callers need to adjust their behavior based on the exact failure.
28  */
29 public final class ErrnoException extends Exception {
30     private final String functionName;
31 
32     /**
33      * The errno value, for comparison with the {@code E} constants in {@link OsConstants}.
34      */
35     public final int errno;
36 
37     /**
38      * Constructs an instance with the given function name and errno value.
39      */
ErrnoException(String functionName, int errno)40     public ErrnoException(String functionName, int errno) {
41         this.functionName = functionName;
42         this.errno = errno;
43     }
44 
45     /**
46      * Constructs an instance with the given function name, errno value, and cause.
47      */
ErrnoException(String functionName, int errno, Throwable cause)48     public ErrnoException(String functionName, int errno, Throwable cause) {
49         super(cause);
50         this.functionName = functionName;
51         this.errno = errno;
52     }
53 
54     /**
55      * Converts the stashed function name and errno value to a human-readable string.
56      * We do this here rather than in the constructor so that callers only pay for
57      * this if they need it.
58      */
getMessage()59     @Override public String getMessage() {
60         String errnoName = OsConstants.errnoName(errno);
61         if (errnoName == null) {
62             errnoName = "errno " + errno;
63         }
64         String description = Libcore.os.strerror(errno);
65         return functionName + " failed: " + errnoName + " (" + description + ")";
66     }
67 
68     /**
69      * Throws an {@link IOException} with a message based on {@link #getMessage()} and with this
70      * instance as the cause.
71      *
72      * <p>This method always terminates by throwing the exception. Callers can write
73      * {@code throw e.rethrowAsIOException()} to make that clear to the compiler.
74      */
rethrowAsIOException()75     public @NonNull IOException rethrowAsIOException() throws IOException {
76         IOException newException = new IOException(getMessage());
77         newException.initCause(this);
78         throw newException;
79     }
80 
81     /**
82      * Throws a {@link SocketException} with a message based on {@link #getMessage()} and with this
83      * instance as the cause.
84      *
85      * <p>This method always terminates by throwing the exception. Callers can write
86      * {@code throw e.rethrowAsIOException()} to make that clear to the compiler.
87      */
rethrowAsSocketException()88     public @NonNull SocketException rethrowAsSocketException() throws SocketException {
89         throw new SocketException(getMessage(), this);
90     }
91 }
92