Skip to content

Commit 29129dc

Browse files
committed
Show error if unable to load libirecovery on Linux (#278), clean up native library mappings
1 parent 50c49c7 commit 29129dc

File tree

5 files changed

+104
-62
lines changed

5 files changed

+104
-62
lines changed

src/main/java/airsquared/blobsaver/app/LibimobiledeviceUtil.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,16 @@ private static PointerByReference waitForRecovery() throws LibimobiledeviceExcep
183183
if (!sleep(1000)) {
184184
return null;
185185
}
186-
errorCode = Libirecovery.open(irecvClient);
186+
try {
187+
errorCode = Libirecovery.open(irecvClient);
188+
} catch (UnsatisfiedLinkError e) {
189+
if (Platform.isLinux()) {
190+
throw new LibimobiledeviceException("Error: libirecovery not found.\n\n" +
191+
"Please ensure you have libirecovery installed as libirecovery.so, and not as libirecovery-1.0.so.", null, 0, false);
192+
} else {
193+
throw e;
194+
}
195+
}
187196
}
188197
throwIfNeeded(errorCode, ErrorCodeType.irecv_error);
189198
return irecvClient;
@@ -259,11 +268,11 @@ private static Pointer getMobileGestaltKey(String key) throws LibimobiledeviceEx
259268
PointerByReference diagnosticsRelayClient = new PointerByReference();
260269
throwIfNeeded(diagnostics_relay_client_new(device.getValue(), service.getValue(), diagnosticsRelayClient), ErrorCodeType.diagnostics_relay_error);
261270

262-
Pointer keys = Libplist.plist_new_array();
263-
Libplist.plist_array_append_item(keys, Libplist.plist_new_string(key));
271+
Pointer keys = Libplist.newArray();
272+
Libplist.arrayAppendItem(keys, Libplist.newString(key));
264273
PointerByReference plistResult = new PointerByReference();
265274
throwIfNeeded(diagnostics_relay_query_mobilegestalt(diagnosticsRelayClient.getValue(), keys, plistResult), ErrorCodeType.diagnostics_relay_error);
266-
Pointer plistApnonce = Libplist.plist_dict_get_item(Libplist.plist_dict_get_item(plistResult.getValue(), "MobileGestalt"), key);
275+
Pointer plistApnonce = Libplist.dictGetItem(Libplist.dictGetItem(plistResult.getValue(), "MobileGestalt"), key);
267276

268277
diagnostics_relay_goodbye(diagnosticsRelayClient.getValue());
269278
diagnostics_relay_client_free(diagnosticsRelayClient.getValue());
@@ -276,7 +285,7 @@ private static Pointer getMobileGestaltKey(String key) throws LibimobiledeviceEx
276285

277286
private static String plistDataToString(Pointer plist, ByteOrder byteOrder) {
278287
IntByReference apnonceLength = new IntByReference();
279-
byte[] apnonceBytes = Libplist.plist_get_data_ptr(plist, apnonceLength).getByteArray(0, apnonceLength.getValue());
288+
byte[] apnonceBytes = Libplist.getDataPtr(plist, apnonceLength).getByteArray(0, apnonceLength.getValue());
280289
String toReturn = Utils.bytesToHex(apnonceBytes, byteOrder);
281290
Libplist.free(plist);
282291

@@ -369,7 +378,7 @@ public void showErrorAlert() {
369378
String message = getMessage();
370379
if (reportable) {
371380
Utils.showReportableError(message);
372-
} else if (errorType.equals(ErrorCodeType.idevice_error) && errorCode == -3 && Platform.isWindows()) {
381+
} else if (ErrorCodeType.idevice_error.equals(errorType) && errorCode == -3 && Platform.isWindows()) {
373382
message += "\n\nEnsure iTunes or Apple's iOS Drivers are installed.";
374383
ButtonType downloadItunes = new ButtonType("Download iTunes");
375384
if (downloadItunes.equals(Utils.showUnreportableError(message, downloadItunes))) {

src/main/java/airsquared/blobsaver/app/natives/Libimobiledevice.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
package airsquared.blobsaver.app.natives;
2020

21-
import com.sun.jna.Native;
2221
import com.sun.jna.Pointer;
2322
import com.sun.jna.ptr.PointerByReference;
2423

@@ -59,6 +58,6 @@ public class Libimobiledevice {
5958
public static native void idevice_free(Pointer idevice);
6059

6160
static {
62-
Native.register(Libimobiledevice.class, "imobiledevice");
61+
NativeUtils.register(Libimobiledevice.class, "imobiledevice");
6362
}
6463
}

src/main/java/airsquared/blobsaver/app/natives/Libirecovery.java

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
package airsquared.blobsaver.app.natives;
2020

21-
import com.sun.jna.Native;
21+
import airsquared.blobsaver.app.natives.NativeUtils.CFunctionName;
2222
import com.sun.jna.Pointer;
2323
import com.sun.jna.Structure;
2424
import com.sun.jna.ptr.PointerByReference;
@@ -32,43 +32,25 @@ public static int open(PointerByReference irecv_client) {
3232
return irecv_open_with_ecid(irecv_client, 0);
3333
}
3434

35-
public static int close(Pointer irecv_client) {
36-
return irecv_close(irecv_client);
37-
}
38-
39-
public static int setEnv(Pointer irecv_client, String variable, String value) {
40-
return irecv_setenv(irecv_client, variable, value);
41-
}
42-
43-
public static int saveEnv(Pointer irecv_client) {
44-
return irecv_saveenv(irecv_client);
45-
}
46-
47-
public static int reboot(Pointer irecv_client) {
48-
return irecv_reboot(irecv_client);
49-
}
50-
51-
public static int sendCommand(Pointer irecv_client, String command) {
52-
return irecv_send_command(irecv_client, command);
53-
}
54-
55-
public static irecv_device_info getDeviceInfo(Pointer irecv_client) {
56-
return irecv_get_device_info(irecv_client);
57-
}
58-
5935
private static native int irecv_open_with_ecid(PointerByReference irecv_client, long ecid);
6036

61-
private static native int irecv_close(Pointer irecv_client);
37+
@CFunctionName("irecv_close")
38+
public static native int close(Pointer irecv_client);
6239

63-
private static native int irecv_setenv(Pointer irecv_client, String variable, String value);
40+
@CFunctionName("irecv_setenv")
41+
public static native int setEnv(Pointer irecv_client, String variable, String value);
6442

65-
private static native int irecv_saveenv(Pointer irecv_client);
43+
@CFunctionName("irecv_saveenv")
44+
public static native int saveEnv(Pointer irecv_client);
6645

67-
private static native int irecv_reboot(Pointer irecv_client);
46+
@CFunctionName("irecv_reboot")
47+
public static native int reboot(Pointer irecv_client);
6848

69-
private static native int irecv_send_command(Pointer irecv_client, String command);
49+
@CFunctionName("irecv_send_command")
50+
public static native int sendCommand(Pointer irecv_client, String command);
7051

71-
private static native irecv_device_info irecv_get_device_info(Pointer irecv_client);
52+
@CFunctionName("irecv_get_device_info")
53+
public static native irecv_device_info getDeviceInfo(Pointer irecv_client);
7254

7355
@SuppressWarnings({"unused", "SpellCheckingInspection"})
7456
@Structure.FieldOrder({"cpid", "cprv", "cpfm", "scep", "bdid", "ecid", "ibfl", "srnm", "imei", "srtg", "serial_string", "ap_nonce", "ap_nonce_size", "sep_nonce", "sep_nonce_size"})
@@ -83,7 +65,8 @@ public static class irecv_device_info extends Structure {
8365
public int sep_nonce_size;
8466
}
8567

68+
8669
static {
87-
Native.register(Libirecovery.class, "irecovery");
70+
NativeUtils.register(Libirecovery.class, "irecovery");
8871
}
8972
}

src/main/java/airsquared/blobsaver/app/natives/Libplist.java

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,38 @@
1818

1919
package airsquared.blobsaver.app.natives;
2020

21-
import com.sun.jna.Native;
21+
import airsquared.blobsaver.app.natives.NativeUtils.CFunctionName;
2222
import com.sun.jna.Pointer;
2323
import com.sun.jna.ptr.IntByReference;
2424
import com.sun.jna.ptr.PointerByReference;
2525

2626
public class Libplist {
2727

28-
public static void getStringVal(Pointer plist, PointerByReference value) {
29-
plist_get_string_val(plist, value);
30-
}
31-
32-
public static void free(Pointer plist) {
33-
plist_free(plist);
34-
}
35-
36-
public static void toXml(Pointer plist, PointerByReference plist_xml, PointerByReference length) {
37-
plist_to_xml(plist, plist_xml, length);
38-
}
39-
40-
public static native Pointer plist_new_array();
28+
@CFunctionName("plist_new_array")
29+
public static native Pointer newArray();
4130

42-
public static native void plist_array_append_item(Pointer plist_t, Pointer plist_t_item);
31+
@CFunctionName("plist_array_append_item")
32+
public static native void arrayAppendItem(Pointer plist_t, Pointer plist_t_item);
4333

44-
public static native Pointer plist_new_string(String val);
34+
@CFunctionName("plist_new_string")
35+
public static native Pointer newString(String val);
4536

46-
public static native Pointer plist_dict_get_item(Pointer plist, String key);
37+
@CFunctionName("plist_dict_get_item")
38+
public static native Pointer dictGetItem(Pointer plist, String key);
4739

48-
public static native Pointer plist_get_data_ptr(Pointer plist, IntByReference length);
40+
@CFunctionName("plist_get_data_ptr")
41+
public static native Pointer getDataPtr(Pointer plist, IntByReference length);
4942

50-
private static native void plist_get_string_val(Pointer plist, PointerByReference value);
43+
@CFunctionName("plist_get_string_val")
44+
public static native void getStringVal(Pointer plist, PointerByReference value);
5145

52-
private static native void plist_free(Pointer plist);
46+
@CFunctionName("plist_free")
47+
public static native void free(Pointer plist);
5348

54-
private static native void plist_to_xml(Pointer plist, PointerByReference plist_xml, PointerByReference length);
49+
@CFunctionName("plist_to_xml")
50+
public static native void toXml(Pointer plist, PointerByReference plist_xml, PointerByReference length);
5551

5652
static {
57-
Native.register(Libplist.class, "plist");
53+
NativeUtils.register(Libplist.class, "plist");
5854
}
5955
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2021 airsquared
3+
*
4+
* This file is part of blobsaver.
5+
*
6+
* blobsaver is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, version 3 of the License.
9+
*
10+
* blobsaver is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with blobsaver. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
package airsquared.blobsaver.app.natives;
20+
21+
import com.sun.jna.FunctionMapper;
22+
import com.sun.jna.Library;
23+
import com.sun.jna.Native;
24+
import com.sun.jna.NativeLibrary;
25+
26+
import java.lang.annotation.Documented;
27+
import java.lang.annotation.ElementType;
28+
import java.lang.annotation.Retention;
29+
import java.lang.annotation.RetentionPolicy;
30+
import java.lang.annotation.Target;
31+
import java.util.Map;
32+
33+
final class NativeUtils {
34+
35+
36+
private static final Map<String, ?> libraryOptions = Map.of(Library.OPTION_CLASSLOADER, NativeUtils.class.getClassLoader(),
37+
Library.OPTION_FUNCTION_MAPPER, (FunctionMapper) (lib, method) ->
38+
method.isAnnotationPresent(CFunctionName.class) ?
39+
method.getAnnotation(CFunctionName.class).value() : method.getName());
40+
41+
/**
42+
* Same exact implementation as Native.register(Class, String), except it
43+
* also includes a function mapper for methods annotated with @CFunctionName
44+
*/
45+
static void register(Class<?> cls, String libName) {
46+
Native.register(cls, NativeLibrary.getInstance(libName, libraryOptions));
47+
}
48+
49+
@Documented
50+
@Retention(RetentionPolicy.RUNTIME)
51+
@Target(ElementType.METHOD)
52+
@interface CFunctionName {
53+
String value();
54+
}
55+
}

0 commit comments

Comments
 (0)