1.什么是libimobiledevice?
A cross-platform software protocol library and tools to communicate with iOS? devices natively.
libimobiledevice is a cross-platform software library that talks the protocols to support iPhone?, iPod Touch?, iPad? and Apple TV? devices. Unlike other projects, it does not depend on using any existing proprietary libraries and does not require jailbreaking. It allows other software to easily access the device's filesystem, retrieve information about the device and it's internals, backup/restore the device, manage SpringBoard? icons, manage installed applications, retrieve addressbook/calendars/notes and bookmarks and (using libgpod) synchronize music and video to the device. The library is in development since August 2007 with the goal to bring support for these devices to the Linux Desktop.
官方網站:http://www.libimobiledevice.org
github地址:https://github.com/libimobiledevice
2.libimobiledevice目前的運用:
PP助手,itools, 愛思助手,xy助手等一大批蘋果助手類軟件,底層全部都是使用的此庫。
3.快速直接安裝libmobiledevice的方法
在MacOS下安裝可以使用brew,類似Ubuntu中的apt-get
brew update
brew install libimobiledevice
#libimobiledevice中并不包含ipa的安裝命令,所以還需要安裝
brew install ideviceinstaller
Ubuntu下安裝需要添加一個新的軟件庫,里面包含了libimobiledevice
sudo add-apt-repository ppa:pmcenery/ppa
sudo apt-get update
apt-get install libimobiledevice-utils
sudo apt-get install ideviceinstaller
常用功能
安裝ipa包,卸載應用
//命令安裝一個ipa文件到手機上,如果是企業簽名的,非越獄機器也可以直接安裝了。
ideviceinstaller -I xxx.ipa
//命令卸載應用,需要知道此應用的bundleID
ideviceinstaller -U [bundleID]
查看系統日志
idevicesyslog
查看當前已連接的設備的UUID
idevice_id --list
截圖
idevicescreenshot
查看設備信息
ideviceinfo
獲取設備時間
idevicedate
設置代理(可以用于轉發端口,比如將ssh的端口映射到電腦,這樣沒有網絡也可以ssh登錄)
iproxy
掛載DeveloperDiskImage,用于調試
ideviceimagemounter
獲取設備名稱
idevicename
調試程序(需要預先掛載DeveloperImage)
idevicedebug
查看和操作設備的描述文件
ideviceprovision list
掛載文件系統工具:ifuse
ifuse是一個依賴libimobiledevice庫的工具,所以必須首先安裝libimobiledevice
brew install osxfuse
brew install ifuse
掛載某應用的整個沙盒目錄
ifuse --container [要掛載的應用的bundleID] [掛載點]
如果是越獄的設備,并且配置好了,可以使用下面命令掛載整個iphone文件系統(暫時沒試過,還沒有開始研究越獄設備)
ifuse --root [掛載點]
4.手動編譯
github:https://github.com/libimobiledevice/libimobiledevice
安裝依賴軟件和庫
brew install openssl
brew install libplist
brew install usbmuxd//包含libusbmuxd
#brew install make //make不需要安裝,系統自帶
brew install autoconf//里面包含autoheader
brew install automake//包含automake
brew install libtool
brew install pkg-config
#brew install gcc//系統自帶
生成Makefile,必須指定openssl的路徑,由于openssl的漏洞,mac不在支持openssl,不支持將openssl的庫加入庫路徑,所以必須指定路徑
./autogen.sh openssl_CFLAGS=/usr/local/opt/openssl/include openssl_LIBS=/usr/local/opt/openssl/lib
編譯
make
安裝
sudo make install
5.什么是Makefile
Linux 環境下的程序員如果不會使用GNU make來構建和管理自己的工程,應該不能算是一個合格的專業程序員,至少不能稱得上是 Unix程序員。在 Linux(unix )環境下使用GNU 的make工具能夠比較容易的構建一個屬于你自己的工程,整個工程的編譯只需要一個命令就可以完成編譯、連接以至于最后的執行。不過這需要我們投入一些時間去完成一個或者多個稱之為Makefile 文件的編寫。
所要完成的Makefile 文件描述了整個工程的編譯、連接等規則。其中包括:工程中的哪些源文件需要編譯以及如何編譯、需要創建那些庫文件以及如何創建這些庫文件、如何最后產生我們想要的可執行文件。盡管看起來可能是很復雜的事情,但是為工程編寫Makefile 的好處是能夠使用一行命令來完成“自動化編譯”,一旦提供一個(通常對于一個工程來說會是多個)正確的 Makefile。編譯整個工程你所要做的唯一的一件事就是在shell 提示符下輸入make命令。整個工程完全自動編譯,極大提高了效率。
make是一個命令工具,它解釋Makefile 中的指令(應該說是規則)。在Makefile文件中描述了整個工程所有文件的編譯順序、編譯規則。Makefile 有自己的書寫格式、關鍵字、函數。像C 語言有自己的格式、關鍵字和函數一樣。而且在Makefile 中可以使用系統shell所提供的任何命令來完成想要的工作。Makefile(在其它的系統上可能是另外的文件名)在絕大多數的IDE 開發環境中都在使用,已經成為一種工程的編譯方法。
使用Makefile例子
1、建目錄
$ mkdir helloword
$ cd helloworld
2、 hello.c
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello word!\n");
return 0;
}
3.首先使用gcc編譯
gcc -o hello hello.c
./hello
output:hello word!
4.使用Makefile編譯
在工作目錄建立Makefile文件
hello:hello.c
gcc -o hello hello.c
clean:
rm hello
使用make編譯
make
output:gcc -o hello hello.c
./hello
output:hello word!
5.Autoconf和Automake使用
1.生成configure
autoscan
ls
autoscan.log configure.scan hello.c
2.生成configure.ac
現在將configure.scan改名為configure.ac,并且編輯它,按下面的內容修改,去掉無關的語句:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE(hello, 1.0)
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
3.執行aclocal和autoconf
aclocal
ls
aclocal.m4 autom4te.cache autoscan.log configure.ac configure.scan hello.c
autoconf
ls
aclocal.m4 autom4te.cache autoscan.log configure configure.ac configure.scan hello.c
可以看到configure.ac內容是一些宏定義,這些宏經autoconf處理后會變成檢查系統特性、環境變量、軟件必須的參數的shell腳本。
autoconf 是用來生成自動配置軟件源代碼腳本(configure)的工具。configure腳本能獨立于autoconf運行,且在運行的過程中,不需要用戶的干預。
要生成configure文件,你必須告訴autoconf如何找到你所用的宏。方式是使用aclocal程序來生成你的aclocal.m4。
aclocal根據configure.ac文件的內容,自動生成aclocal.m4文件。aclocal是一個perl 腳本程序,它的定義是:“aclocal - create aclocal.m4 by scanning configure.ac”。
autoconf從configure.ac這個列舉編譯軟件時所需要各種參數的模板文件中創建configure。
autoconf需要GNU m4宏處理器來處理aclocal.m4,生成configure腳本。
m4是一個宏處理器。將輸入拷貝到輸出,同時將宏展開。宏可以是內嵌的,也可以是用戶定義的。除了可以展開宏,m4還有一些內建的函數,用來引用文件,執行命令,整數運算,文本操作,循環等。m4既可以作為編譯器的前端,也可以單獨作為一個宏處理器.
4.執行autoheader
autoheader
ls
aclocal.m4 autom4te.cache autoscan.log config.h.in configure configure.ac configure.scan hello.c
5.新建Makefile.am
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=hello
hello_SOURCES=hello.c
6.運行automake
automake --add-missing
configure.ac:6: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:6: https://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:11: installing './compile'
configure.ac:6: installing './install-sh'
configure.ac:6: installing './missing'
Makefile.am: installing './depcomp'
ls
Makefile.am aclocal.m4 autoscan.log config.h.in configure.ac depcomp install-sh
Makefile.in autom4te.cache compile configure configure.scan hello.c missing
automake會根據Makefile.am文件產生一些文件,包含最重要的Makefile.in。
7.執行configure生成Makefile
./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
ls
Makefile aclocal.m4 compile config.log configure.ac hello.c stamp-h1
Makefile.am autom4te.cache config.h config.status configure.scan install-sh
Makefile.in autoscan.log config.h.in configure depcomp missing
8.make及運行
make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-am
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc -g -O2 -o hello hello.o
ls
Makefile aclocal.m4 compile config.log configure.ac hello install-sh
Makefile.am autom4te.cache config.h config.status configure.scan hello.c missing
Makefile.in autoscan.log config.h.in configure depcomp hello.o stamp-h1
./hello
hello word!
autotools命令詳解:
1、 autoscan
autoscan是用來掃描源代碼目錄生成configure.scan文件的。autoscan可以用目錄名做為參數,但如果你不使用參數的話,那么autoscan將認為使用的是當前目錄。autoscan將掃描你所指定目錄中的源文件,并創建configure.scan文件。
2、 configure.scan
configure.scan包含了系統配置的基本選項,里面都是一些宏定義。我們需要將它改名為configure.ac
3、 aclocal
aclocal是一個perl 腳本程序。aclocal根據configure.ac文件的內容,自動生成aclocal.m4文件。aclocal的定義是:“aclocal - create aclocal.m4 by scanning configure.ac”。
4、 autoconf
使用autoconf,根據configure.in和aclocal.m4來產生configure文件。configure是一個腳本,它能設置源程序來適應各種不同的操作系統平臺,并且根據不同的系統來產生合適的Makefile,從而可以使你的源代碼能在不同的操作系統平臺上被編譯出來。
configure.ac文件的內容是一些宏,這些宏經過autoconf 處理后會變成檢查系統特性、環境變量、軟件必須的參數的shell腳本。configure.ac文件中的宏的順序并沒有規定,但是你必須在所有宏的最前面和最后面分別加上AC_INIT宏和AC_OUTPUT宏。
在configure.ini中:
#號表示注釋,這個宏后面的內容將被忽略。
AC_INIT(FILE) //這個宏用來檢查源代碼所在的路徑。
AM_INIT_AUTOMAKE(PACKAGE, VERSION) //這個宏是必須的,它描述了我們將要生成的軟件包的名字及其版本號:PACKAGE是軟件包的名字,VERSION是版本號。當你使用make dist命令時,它會給你生成一個類似helloworld-1.0.tar.gz的軟件發行包,其中就有對應的軟件包的名字和版本號。
AC_PROG_CC //這個宏將檢查系統所用的C編譯器。
AC_OUTPUT(FILE) //這個宏是我們要輸出的Makefile的名字。
我們在使用automake時,實際上還需要用到其他的一些宏,但我們可以用aclocal 來幫我們自動產生。執行aclocal后我們會得到aclocal.m4文件。 產生了configure.ac和aclocal.m4 兩個宏文件后,我們就可以使用autoconf來產生configure文件了。
5、 Makefile.am
Makefile.am是用來生成Makefile.in的,需要你手工書寫。Makefile.am中定義了一些內容:
AUTOMAKE_OPTIONS //在執行automake時,它會檢查目錄下是否存在標準GNU軟件包中應具備的各種文件,例如AUTHORS、ChangeLog、NEWS等文件。我們將其設置成foreign時,automake會改用一般軟件包的標準來檢查。
bin_PROGRAMS //這個是指定我們所要產生的可執行文件的文件名。如果你要產生多個可執行文件,那么在各個名字間用空格隔開。
helloworld_SOURCES //這個是指定產生“helloworld”時所需要的源代碼。如果它用到了多個源文件,那么請使用空格符號將它們隔開。比如需要helloworld.h,helloworld.c那么請寫成helloworld_SOURCES= helloworld.h helloworld.c。
如果你在bin_PROGRAMS定義了多個可執行文件,則對應每個可執行文件都要定義相對的filename_SOURCES。
6、 automake
使用automake,根據configure.in和Makefile.am來產生Makefile.in。
--add-missing //定義是“add missing standard files to package”,它會讓automake加入一個標準的軟件包所必須的一些文件。
用automake產生出來的Makefile.in文件是符合GNU Makefile慣例的,接下來我們只要執行configure這個shell 腳本就可以產生合適的 Makefile 文件了。
7、 Makefile
在符合GNU Makefiel慣例的Makefile中,包含了一些基本的預先定義的操作:
make //根據Makefile編譯源代碼,連接,生成目標文件,可執行文件。
make clean //清除上次的make命令所產生的object文件(后綴為“.o”的文件)及可執行文件。
make install //將編譯成功的可執行文件安裝到系統目錄中,一般為/usr/local/bin目錄。
make list //產生發布軟件包文件(即distribution package)。這個命令會將可執行文件及相關文件打包成一個tar.gz壓縮的文件用來作為發布軟件的軟件包。它會在當前目錄下生成一個名字類似“PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSION,是我們在configure.ac中定義的AM_INIT_AUTOMAKE(PACKAGE, VERSION)。
make distcheck //生成發布軟件包并對其進行測試檢查,以確定發布包的正確性。這個操作將自動把壓縮包文件解開,然后執行configure命令,并且執行make,來確認編譯不出現錯誤,最后提示你軟件包已經準備好,可以發布了。
make distclean //類似make clean,但同時也將configure生成的文件全部刪除掉,包括Makefile。
5.代碼使用libimobiledevice
//
// main.m
// testlibimobiledevice
//
// Created by dujianjie on 2018/6/26.
// Copyright ? 2018年 dujianjie. All rights reserved.
//
#include <pthread.h>
#include <libimobiledevice/house_arrest.h>
#include <libimobiledevice/afc.h>
#include <libimobiledevice/lockdown.h>
#import <libimobiledevice/libimobiledevice.h>
#import <Foundation/Foundation.h>
void* modify(void *info) {
int *error = malloc(sizeof(int));
size_t len = strlen((char *)info);
char *udid = malloc(len+1);
if (!udid) {
*error = -10;
goto l_udid;
}
memset(udid, 0, len+1);
memcpy(udid, info, len);
idevice_t device = NULL;
idevice_new(&device, udid);
if (!device) {
*error = -10;
goto l_device;
}
NSLog(@"idevice_new success");
lockdownd_client_t lockdownd_client = NULL;
lockdownd_error_t lockdownd_err = LOCKDOWN_E_UNKNOWN_ERROR;
lockdownd_err = lockdownd_client_new_with_handshake(device, &lockdownd_client, "handshake");
if (lockdownd_err != LOCKDOWN_E_SUCCESS) {
*error = -10;
goto l_device;
}
NSLog(@"lockdownd_client_new_with_handshake success");
// lockdownd_client_free(lockdownd_client);
house_arrest_error_t err = 0;
house_arrest_client_t client = NULL;
err = house_arrest_client_start_service(device, &client, NULL);
if(err != HOUSE_ARREST_E_SUCCESS) {
*error = err;
goto l_device;
}
NSLog(@"house_arrest_client_start_service success");
err = house_arrest_send_command(client, "VendContainer", "com.cvte.EasiAir");
if(err != HOUSE_ARREST_E_SUCCESS) {
*error = err;
goto l_house;
}
NSLog(@"house_arrest_send_command success");
plist_t dict = NULL;
err = house_arrest_get_result(client, &dict);
if(err != HOUSE_ARREST_E_SUCCESS) {
NSLog(@"house_arrest_get_result :%d", err);
*error = err;
goto l_house;
}
char *xml = NULL;
uint32_t length = 0;
plist_to_xml(dict, &xml, &length);
NSLog(@"house_arrest_get_result success:%s",xml);
if (xml) free(xml);
plist_t node = plist_dict_get_item(dict, "Status");
if (!node) {
*error = -4;
goto l_list;
}
char *status = NULL;
plist_get_string_val(node, &status);
if (!status) {
*error = -4;
goto l_list;
}
NSLog(@"status:%s", status);
if (strcmp(status, "Complete")!=0) {
*error = -4;
goto l_status;
}
NSLog(@"house_arrest_send_command success");
afc_client_t afc_client = NULL;
afc_error_t afc_err = afc_client_new_from_house_arrest_client(client, &afc_client);
if (afc_err != AFC_E_SUCCESS) {
*error = afc_err;
goto l_status;
}
NSLog(@"afc_client_new_from_house_arrest_client success");
afc_err = afc_make_directory(afc_client, "Documents/Custom_dujj");
if (afc_err != AFC_E_SUCCESS) {
*error = afc_err;
goto l_status;
}
NSLog(@"afc_make_directory success");
l_status:
free(status);
l_list:
plist_free(dict);
l_house:
house_arrest_client_free(client);
l_device:
idevice_free(device);
l_udid:
free(udid);
return error;
}
void idevice_event_callback(const idevice_event_t *event, void *user_data) {
switch(event->event) {
case IDEVICE_DEVICE_ADD:{
NSLog(@"add device %s", event->udid);
static pthread_t devmon = 0;
if (devmon == 0)
pthread_create(&devmon, NULL, modify, (void *)event->udid);
}break;
case IDEVICE_DEVICE_REMOVE:{
NSLog(@"remove device %s", event->udid);
}break;
case IDEVICE_DEVICE_PAIRED:{
NSLog(@"paired device %s", event->udid);
}break;
default: {
}break;
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
idevice_set_debug_level(1);
idevice_error_t err = idevice_event_subscribe(idevice_event_callback, NULL);
struct timespec ts;
ts.tv_sec = 180;
ts.tv_nsec = 0;
while(1) {
nanosleep(&ts, NULL);
}
err = idevice_event_unsubscribe();
}
return 0;
}
6.libimobiledevice內部魔法
1.usbmuxd
A socket daemon to multiplex connections from and to iOS devices
2.守護進程
守護進程時一個在后臺運行并且不受任何終端控制的進程。
百度百科
3.udev
Linux kernel2.6系列的設備管理器,在libimobiledevice中用于監控usb熱插拔。
百度百科
4.systemd
Systemd 是 Linux 系統中最新的初始化系統(init),它主要的設計目標是克服 sysvinit 固有的缺點,提高系統的啟動速度。
百度百科
7.libimobiledevice結構圖
8.libimobiledevice提供的iOS服務
- com.apple.afc,文件系統服務
- com.apple.afc2,越獄文件系統服務
- com.apple.mobile.installation_proxy,應用服務
- com.apple.mobile.house_arrest,應用內文件服務
- com.apple.mobile.notification_proxy,通知服務
更多服務地址