diff options
64 files changed, 3130 insertions, 1095 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..e995b30 --- /dev/null +++ b/.github/FUNDING.yml | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | github: nikias | ||
| 2 | patreon: nikias | ||
| 3 | custom: ["https://www.paypal.me/NikiasBassen"] | ||
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0298939..fbbf10a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml | |||
| @@ -2,6 +2,7 @@ name: build | |||
| 2 | 2 | ||
| 3 | on: | 3 | on: |
| 4 | push: | 4 | push: |
| 5 | pull_request: | ||
| 5 | schedule: | 6 | schedule: |
| 6 | - cron: '0 0 1 * *' | 7 | - cron: '0 0 1 * *' |
| 7 | 8 | ||
| @@ -17,28 +18,28 @@ jobs: | |||
| 17 | run: | | 18 | run: | |
| 18 | echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV | 19 | echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV |
| 19 | - name: fetch libplist | 20 | - name: fetch libplist |
| 20 | uses: dawidd6/action-download-artifact@v3 | 21 | uses: dawidd6/action-download-artifact@v6 |
| 21 | with: | 22 | with: |
| 22 | github_token: ${{secrets.GITHUB_TOKEN}} | 23 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 23 | workflow: build.yml | 24 | workflow: build.yml |
| 24 | name: libplist-latest_${{env.target_triplet}} | 25 | name: libplist-latest_${{env.target_triplet}} |
| 25 | repo: libimobiledevice/libplist | 26 | repo: libimobiledevice/libplist |
| 26 | - name: fetch libusbmuxd | 27 | - name: fetch libusbmuxd |
| 27 | uses: dawidd6/action-download-artifact@v3 | 28 | uses: dawidd6/action-download-artifact@v6 |
| 28 | with: | 29 | with: |
| 29 | github_token: ${{secrets.GITHUB_TOKEN}} | 30 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 30 | workflow: build.yml | 31 | workflow: build.yml |
| 31 | name: libusbmuxd-latest_${{env.target_triplet}} | 32 | name: libusbmuxd-latest_${{env.target_triplet}} |
| 32 | repo: libimobiledevice/libusbmuxd | 33 | repo: libimobiledevice/libusbmuxd |
| 33 | - name: fetch libimobiledevice-glue | 34 | - name: fetch libimobiledevice-glue |
| 34 | uses: dawidd6/action-download-artifact@v3 | 35 | uses: dawidd6/action-download-artifact@v6 |
| 35 | with: | 36 | with: |
| 36 | github_token: ${{secrets.GITHUB_TOKEN}} | 37 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 37 | workflow: build.yml | 38 | workflow: build.yml |
| 38 | name: libimobiledevice-glue-latest_${{env.target_triplet}} | 39 | name: libimobiledevice-glue-latest_${{env.target_triplet}} |
| 39 | repo: libimobiledevice/libimobiledevice-glue | 40 | repo: libimobiledevice/libimobiledevice-glue |
| 40 | - name: fetch libtatsu | 41 | - name: fetch libtatsu |
| 41 | uses: dawidd6/action-download-artifact@v3 | 42 | uses: dawidd6/action-download-artifact@v6 |
| 42 | with: | 43 | with: |
| 43 | github_token: ${{secrets.GITHUB_TOKEN}} | 44 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 44 | workflow: build.yml | 45 | workflow: build.yml |
| @@ -84,28 +85,28 @@ jobs: | |||
| 84 | pip3 install --break-system-packages cython | 85 | pip3 install --break-system-packages cython |
| 85 | shell: bash | 86 | shell: bash |
| 86 | - name: fetch libplist | 87 | - name: fetch libplist |
| 87 | uses: dawidd6/action-download-artifact@v3 | 88 | uses: dawidd6/action-download-artifact@v6 |
| 88 | with: | 89 | with: |
| 89 | github_token: ${{secrets.GITHUB_TOKEN}} | 90 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 90 | workflow: build.yml | 91 | workflow: build.yml |
| 91 | name: libplist-latest_macOS | 92 | name: libplist-latest_macOS |
| 92 | repo: libimobiledevice/libplist | 93 | repo: libimobiledevice/libplist |
| 93 | - name: fetch libusbmuxd | 94 | - name: fetch libusbmuxd |
| 94 | uses: dawidd6/action-download-artifact@v3 | 95 | uses: dawidd6/action-download-artifact@v6 |
| 95 | with: | 96 | with: |
| 96 | github_token: ${{secrets.GITHUB_TOKEN}} | 97 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 97 | workflow: build.yml | 98 | workflow: build.yml |
| 98 | name: libusbmuxd-latest_macOS | 99 | name: libusbmuxd-latest_macOS |
| 99 | repo: libimobiledevice/libusbmuxd | 100 | repo: libimobiledevice/libusbmuxd |
| 100 | - name: fetch libimobiledevice-glue | 101 | - name: fetch libimobiledevice-glue |
| 101 | uses: dawidd6/action-download-artifact@v3 | 102 | uses: dawidd6/action-download-artifact@v6 |
| 102 | with: | 103 | with: |
| 103 | github_token: ${{secrets.GITHUB_TOKEN}} | 104 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 104 | workflow: build.yml | 105 | workflow: build.yml |
| 105 | name: libimobiledevice-glue-latest_macOS | 106 | name: libimobiledevice-glue-latest_macOS |
| 106 | repo: libimobiledevice/libimobiledevice-glue | 107 | repo: libimobiledevice/libimobiledevice-glue |
| 107 | - name: fetch libtatsu | 108 | - name: fetch libtatsu |
| 108 | uses: dawidd6/action-download-artifact@v3 | 109 | uses: dawidd6/action-download-artifact@v6 |
| 109 | with: | 110 | with: |
| 110 | github_token: ${{secrets.GITHUB_TOKEN}} | 111 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 111 | workflow: build.yml | 112 | workflow: build.yml |
| @@ -154,6 +155,7 @@ jobs: | |||
| 154 | PYTHON_EXEC_PREFIX=`$PYTHON3_BIN -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('exec_prefix'))"` | 155 | PYTHON_EXEC_PREFIX=`$PYTHON3_BIN -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('exec_prefix'))"` |
| 155 | PYTHON_LIBS_PATH=$PYTHON_EXEC_PREFIX/lib | 156 | PYTHON_LIBS_PATH=$PYTHON_EXEC_PREFIX/lib |
| 156 | PYTHON_FRAMEWORK_PATH=$PYTHON_EXEC_PREFIX/Python3 | 157 | PYTHON_FRAMEWORK_PATH=$PYTHON_EXEC_PREFIX/Python3 |
| 158 | export PYTHON_CPPFLAGS="-I$PYTHON_EXEC_PREFIX/Headers" | ||
| 157 | export PYTHON_LIBS="-L$PYTHON_LIBS_PATH -lpython$PYTHON_VER" | 159 | export PYTHON_LIBS="-L$PYTHON_LIBS_PATH -lpython$PYTHON_VER" |
| 158 | export PYTHON_EXTRA_LDFLAGS="-Wl,-stack_size,1000000 -framework CoreFoundation $PYTHON_FRAMEWORK_PATH" | 160 | export PYTHON_EXTRA_LDFLAGS="-Wl,-stack_size,1000000 -framework CoreFoundation $PYTHON_FRAMEWORK_PATH" |
| 159 | fi | 161 | fi |
| @@ -175,7 +177,7 @@ jobs: | |||
| 175 | name: libimobiledevice-latest_macOS | 177 | name: libimobiledevice-latest_macOS |
| 176 | path: libimobiledevice.tar | 178 | path: libimobiledevice.tar |
| 177 | build-windows: | 179 | build-windows: |
| 178 | runs-on: windows-2019 | 180 | runs-on: windows-latest |
| 179 | defaults: | 181 | defaults: |
| 180 | run: | 182 | run: |
| 181 | shell: msys2 {0} | 183 | shell: msys2 {0} |
| @@ -196,6 +198,8 @@ jobs: | |||
| 196 | base-devel | 198 | base-devel |
| 197 | git | 199 | git |
| 198 | mingw-w64-${{ matrix.arch }}-gcc | 200 | mingw-w64-${{ matrix.arch }}-gcc |
| 201 | mingw-w64-${{ matrix.arch }}-pkg-config | ||
| 202 | mingw-w64-${{ matrix.arch }}-openssl | ||
| 199 | make | 203 | make |
| 200 | libtool | 204 | libtool |
| 201 | autoconf | 205 | autoconf |
| @@ -207,28 +211,28 @@ jobs: | |||
| 207 | echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV | 211 | echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV |
| 208 | git config --global core.autocrlf false | 212 | git config --global core.autocrlf false |
| 209 | - name: fetch libplist | 213 | - name: fetch libplist |
| 210 | uses: dawidd6/action-download-artifact@v3 | 214 | uses: dawidd6/action-download-artifact@v6 |
| 211 | with: | 215 | with: |
| 212 | github_token: ${{secrets.GITHUB_TOKEN}} | 216 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 213 | workflow: build.yml | 217 | workflow: build.yml |
| 214 | name: libplist-latest_${{ matrix.arch }}-${{ env.dest }} | 218 | name: libplist-latest_${{ matrix.arch }}-${{ env.dest }} |
| 215 | repo: libimobiledevice/libplist | 219 | repo: libimobiledevice/libplist |
| 216 | - name: fetch libusbmuxd | 220 | - name: fetch libusbmuxd |
| 217 | uses: dawidd6/action-download-artifact@v3 | 221 | uses: dawidd6/action-download-artifact@v6 |
| 218 | with: | 222 | with: |
| 219 | github_token: ${{secrets.GITHUB_TOKEN}} | 223 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 220 | workflow: build.yml | 224 | workflow: build.yml |
| 221 | name: libusbmuxd-latest_${{ matrix.arch }}-${{ env.dest }} | 225 | name: libusbmuxd-latest_${{ matrix.arch }}-${{ env.dest }} |
| 222 | repo: libimobiledevice/libusbmuxd | 226 | repo: libimobiledevice/libusbmuxd |
| 223 | - name: fetch libimobiledevice-glue | 227 | - name: fetch libimobiledevice-glue |
| 224 | uses: dawidd6/action-download-artifact@v3 | 228 | uses: dawidd6/action-download-artifact@v6 |
| 225 | with: | 229 | with: |
| 226 | github_token: ${{secrets.GITHUB_TOKEN}} | 230 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 227 | workflow: build.yml | 231 | workflow: build.yml |
| 228 | name: libimobiledevice-glue-latest_${{ matrix.arch }}-${{ env.dest }} | 232 | name: libimobiledevice-glue-latest_${{ matrix.arch }}-${{ env.dest }} |
| 229 | repo: libimobiledevice/libimobiledevice-glue | 233 | repo: libimobiledevice/libimobiledevice-glue |
| 230 | - name: fetch libtatsu | 234 | - name: fetch libtatsu |
| 231 | uses: dawidd6/action-download-artifact@v3 | 235 | uses: dawidd6/action-download-artifact@v6 |
| 232 | with: | 236 | with: |
| 233 | github_token: ${{secrets.GITHUB_TOKEN}} | 237 | github_token: ${{secrets.GITHUB_TOKEN}} |
| 234 | workflow: build.yml | 238 | workflow: build.yml |
diff --git a/3rd_party/ed25519/Makefile.am b/3rd_party/ed25519/Makefile.am index d8e4e04..438cb53 100644 --- a/3rd_party/ed25519/Makefile.am +++ b/3rd_party/ed25519/Makefile.am | |||
| @@ -15,12 +15,19 @@ libed25519_la_LIBADD = | |||
| 15 | libed25519_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined | 15 | libed25519_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined |
| 16 | libed25519_la_SOURCES = \ | 16 | libed25519_la_SOURCES = \ |
| 17 | add_scalar.c \ | 17 | add_scalar.c \ |
| 18 | ed25519.h \ | ||
| 18 | fe.c \ | 19 | fe.c \ |
| 20 | fe.h \ | ||
| 21 | fixedint.h \ | ||
| 19 | ge.c \ | 22 | ge.c \ |
| 23 | ge.h \ | ||
| 20 | keypair.c \ | 24 | keypair.c \ |
| 21 | key_exchange.c \ | 25 | key_exchange.c \ |
| 26 | precomp_data.h \ | ||
| 22 | sc.c \ | 27 | sc.c \ |
| 28 | sc.h \ | ||
| 23 | seed.c \ | 29 | seed.c \ |
| 24 | sign.c \ | 30 | sign.c \ |
| 25 | sha512.c \ | 31 | sha512.c \ |
| 32 | sha512.h \ | ||
| 26 | verify.c | 33 | verify.c |
diff --git a/3rd_party/libsrp6a-sha512/Makefile.am b/3rd_party/libsrp6a-sha512/Makefile.am index 2acd582..bdacb5f 100644 --- a/3rd_party/libsrp6a-sha512/Makefile.am +++ b/3rd_party/libsrp6a-sha512/Makefile.am | |||
| @@ -25,7 +25,8 @@ libsrp6a_sha512_la_SOURCES = \ | |||
| 25 | t_truerand.c cstr.c \ | 25 | t_truerand.c cstr.c \ |
| 26 | srp.c srp6a_sha512_client.c \ | 26 | srp.c srp6a_sha512_client.c \ |
| 27 | srp.h srp_aux.h cstr.h \ | 27 | srp.h srp_aux.h cstr.h \ |
| 28 | t_sha.c | 28 | t_defines.h t_pwd.h \ |
| 29 | t_sha.c t_sha.h | ||
| 29 | #if !HAVE_OPENSSL | 30 | #if !HAVE_OPENSSL |
| 30 | #libsrp6a_sha512_la_SOURCES += t_sha.c | 31 | #libsrp6a_sha512_la_SOURCES += t_sha.c |
| 31 | #endif | 32 | #endif |
diff --git a/3rd_party/libsrp6a-sha512/cstr.c b/3rd_party/libsrp6a-sha512/cstr.c index 9856f46..58a5638 100644 --- a/3rd_party/libsrp6a-sha512/cstr.c +++ b/3rd_party/libsrp6a-sha512/cstr.c | |||
| @@ -8,72 +8,31 @@ | |||
| 8 | #define MINSIZE 4 /* Absolute minimum - one word */ | 8 | #define MINSIZE 4 /* Absolute minimum - one word */ |
| 9 | 9 | ||
| 10 | static char cstr_empty_string[] = { '\0' }; | 10 | static char cstr_empty_string[] = { '\0' }; |
| 11 | static cstr_allocator * default_alloc = NULL; | ||
| 12 | |||
| 13 | /* | ||
| 14 | * It is assumed, for efficiency, that it is okay to pass more arguments | ||
| 15 | * to a function than are called for, as long as the required arguments | ||
| 16 | * are in proper form. If extra arguments to malloc() and free() cause | ||
| 17 | * problems, define PEDANTIC_ARGS below. | ||
| 18 | */ | ||
| 19 | #ifdef PEDANTIC_ARGS | ||
| 20 | static void * Cmalloc(int n, void * heap) { return malloc(n); } | ||
| 21 | static void Cfree(void * p, void * heap) { free(p); } | ||
| 22 | static cstr_allocator malloc_allocator = { Cmalloc, Cfree, NULL }; | ||
| 23 | #else | ||
| 24 | static cstr_allocator malloc_allocator = { malloc, free, NULL }; | ||
| 25 | #endif | ||
| 26 | |||
| 27 | _TYPE( void ) | ||
| 28 | cstr_set_allocator(cstr_allocator * alloc) | ||
| 29 | { | ||
| 30 | default_alloc = alloc; | ||
| 31 | } | ||
| 32 | 11 | ||
| 33 | _TYPE( cstr * ) | 12 | _TYPE( cstr * ) |
| 34 | cstr_new_alloc(cstr_allocator * alloc) | 13 | cstr_new() |
| 35 | { | 14 | { |
| 36 | cstr * str; | 15 | cstr * str; |
| 37 | 16 | ||
| 38 | if(alloc == NULL) { | 17 | str = (cstr *) malloc(sizeof(cstr)); |
| 39 | if(default_alloc == NULL) { | ||
| 40 | default_alloc = &malloc_allocator; | ||
| 41 | } | ||
| 42 | alloc = default_alloc; | ||
| 43 | } | ||
| 44 | |||
| 45 | str = (cstr *) (*alloc->alloc)(sizeof(cstr), alloc->heap); | ||
| 46 | if(str) { | 18 | if(str) { |
| 47 | str->data = cstr_empty_string; | 19 | str->data = cstr_empty_string; |
| 48 | str->length = str->cap = 0; | 20 | str->length = str->cap = 0; |
| 49 | str->ref = 1; | 21 | str->ref = 1; |
| 50 | str->allocator = alloc; | ||
| 51 | } | 22 | } |
| 52 | return str; | 23 | return str; |
| 53 | } | 24 | } |
| 54 | 25 | ||
| 55 | _TYPE( cstr * ) | 26 | _TYPE( cstr * ) |
| 56 | cstr_new() | 27 | cstr_dup(const cstr * str) |
| 57 | { | ||
| 58 | return cstr_new_alloc(NULL); | ||
| 59 | } | ||
| 60 | |||
| 61 | _TYPE( cstr * ) | ||
| 62 | cstr_dup_alloc(const cstr * str, cstr_allocator * alloc) | ||
| 63 | { | 28 | { |
| 64 | cstr * nstr = cstr_new_alloc(alloc); | 29 | cstr * nstr = cstr_new(); |
| 65 | if(nstr) | 30 | if(nstr) |
| 66 | cstr_setn(nstr, str->data, str->length); | 31 | cstr_setn(nstr, str->data, str->length); |
| 67 | return nstr; | 32 | return nstr; |
| 68 | } | 33 | } |
| 69 | 34 | ||
| 70 | _TYPE( cstr * ) | 35 | _TYPE( cstr * ) |
| 71 | cstr_dup(const cstr * str) | ||
| 72 | { | ||
| 73 | return cstr_dup_alloc(str, NULL); | ||
| 74 | } | ||
| 75 | |||
| 76 | _TYPE( cstr * ) | ||
| 77 | cstr_create(const char * s) | 36 | cstr_create(const char * s) |
| 78 | { | 37 | { |
| 79 | return cstr_createn(s, strlen(s)); | 38 | return cstr_createn(s, strlen(s)); |
| @@ -101,9 +60,9 @@ cstr_clear_free(cstr * str) | |||
| 101 | if(--str->ref == 0) { | 60 | if(--str->ref == 0) { |
| 102 | if(str->cap > 0) { | 61 | if(str->cap > 0) { |
| 103 | memset(str->data, 0, str->cap); | 62 | memset(str->data, 0, str->cap); |
| 104 | (*str->allocator->free)(str->data, str->allocator->heap); | 63 | free(str->data); |
| 105 | } | 64 | } |
| 106 | (*str->allocator->free)(str, str->allocator->heap); | 65 | free(str); |
| 107 | } | 66 | } |
| 108 | } | 67 | } |
| 109 | 68 | ||
| @@ -112,8 +71,8 @@ cstr_free(cstr * str) | |||
| 112 | { | 71 | { |
| 113 | if(--str->ref == 0) { | 72 | if(--str->ref == 0) { |
| 114 | if(str->cap > 0) | 73 | if(str->cap > 0) |
| 115 | (*str->allocator->free)(str->data, str->allocator->heap); | 74 | free(str->data); |
| 116 | (*str->allocator->free)(str, str->allocator->heap); | 75 | free(str); |
| 117 | } | 76 | } |
| 118 | } | 77 | } |
| 119 | 78 | ||
| @@ -121,7 +80,7 @@ _TYPE( void ) | |||
| 121 | cstr_empty(cstr * str) | 80 | cstr_empty(cstr * str) |
| 122 | { | 81 | { |
| 123 | if(str->cap > 0) | 82 | if(str->cap > 0) |
| 124 | (*str->allocator->free)(str->data, str->allocator->heap); | 83 | free(str->data); |
| 125 | str->data = cstr_empty_string; | 84 | str->data = cstr_empty_string; |
| 126 | str->length = str->cap = 0; | 85 | str->length = str->cap = 0; |
| 127 | } | 86 | } |
| @@ -137,8 +96,7 @@ cstr_alloc(cstr * str, int len) | |||
| 137 | if(len < MINSIZE) | 96 | if(len < MINSIZE) |
| 138 | len = MINSIZE; | 97 | len = MINSIZE; |
| 139 | 98 | ||
| 140 | t = (char *) (*str->allocator->alloc)(len * sizeof(char), | 99 | t = (char *) malloc(len * sizeof(char)); |
| 141 | str->allocator->heap); | ||
| 142 | if(t) { | 100 | if(t) { |
| 143 | if(str->data) { | 101 | if(str->data) { |
| 144 | t[str->length] = 0; | 102 | t[str->length] = 0; |
diff --git a/3rd_party/libsrp6a-sha512/cstr.h b/3rd_party/libsrp6a-sha512/cstr.h index 7cc019a..29afea7 100644 --- a/3rd_party/libsrp6a-sha512/cstr.h +++ b/3rd_party/libsrp6a-sha512/cstr.h | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #define _MSVC15DEXPORT | 38 | #define _MSVC15DEXPORT |
| 39 | #define _MSVC20EXPORT | 39 | #define _MSVC20EXPORT |
| 40 | #define _DLLAPI | 40 | #define _DLLAPI |
| 41 | #if defined(WINDOWS) || defined(WIN32) | 41 | #if defined(WINDOWS) || defined(_WIN32) |
| 42 | #define _CDECL _cdecl | 42 | #define _CDECL _cdecl |
| 43 | #else | 43 | #else |
| 44 | #define _CDECL | 44 | #define _CDECL |
| @@ -51,27 +51,15 @@ | |||
| 51 | extern "C" { | 51 | extern "C" { |
| 52 | #endif /* __cplusplus */ | 52 | #endif /* __cplusplus */ |
| 53 | 53 | ||
| 54 | /* Arguments to allocator methods ordered this way for compatibility */ | ||
| 55 | typedef struct cstr_alloc_st { | ||
| 56 | void * (_CDECL * alloc)(size_t n, void * heap); | ||
| 57 | void (_CDECL * free)(void * p, void * heap); | ||
| 58 | void * heap; | ||
| 59 | } cstr_allocator; | ||
| 60 | |||
| 61 | typedef struct cstr_st { | 54 | typedef struct cstr_st { |
| 62 | char * data; /* Okay to access data and length fields directly */ | 55 | char * data; /* Okay to access data and length fields directly */ |
| 63 | int length; | 56 | int length; |
| 64 | int cap; | 57 | int cap; |
| 65 | int ref; /* Simple reference counter */ | 58 | int ref; /* Simple reference counter */ |
| 66 | cstr_allocator * allocator; | ||
| 67 | } cstr; | 59 | } cstr; |
| 68 | 60 | ||
| 69 | _TYPE( void ) cstr_set_allocator P((cstr_allocator * alloc)); | ||
| 70 | |||
| 71 | _TYPE( cstr * ) cstr_new P((void)); | 61 | _TYPE( cstr * ) cstr_new P((void)); |
| 72 | _TYPE( cstr * ) cstr_new_alloc P((cstr_allocator * alloc)); | ||
| 73 | _TYPE( cstr * ) cstr_dup P((const cstr * str)); | 62 | _TYPE( cstr * ) cstr_dup P((const cstr * str)); |
| 74 | _TYPE( cstr * ) cstr_dup_alloc P((const cstr * str, cstr_allocator * alloc)); | ||
| 75 | _TYPE( cstr * ) cstr_create P((const char * s)); | 63 | _TYPE( cstr * ) cstr_create P((const char * s)); |
| 76 | _TYPE( cstr * ) cstr_createn P((const char * s, int len)); | 64 | _TYPE( cstr * ) cstr_createn P((const char * s, int len)); |
| 77 | 65 | ||
diff --git a/3rd_party/libsrp6a-sha512/t_defines.h b/3rd_party/libsrp6a-sha512/t_defines.h index 447263f..a2a5fe5 100644 --- a/3rd_party/libsrp6a-sha512/t_defines.h +++ b/3rd_party/libsrp6a-sha512/t_defines.h | |||
| @@ -65,7 +65,7 @@ | |||
| 65 | #define _MSVC15DEXPORT | 65 | #define _MSVC15DEXPORT |
| 66 | #define _MSVC20EXPORT | 66 | #define _MSVC20EXPORT |
| 67 | #define _DLLAPI | 67 | #define _DLLAPI |
| 68 | #if defined(WINDOWS) || defined(WIN32) | 68 | #if defined(WINDOWS) || defined(_WIN32) |
| 69 | #define _CDECL _cdecl | 69 | #define _CDECL _cdecl |
| 70 | #else | 70 | #else |
| 71 | #define _CDECL | 71 | #define _CDECL |
| @@ -122,7 +122,7 @@ char *strchr(), *strrchr(), *strtok(); | |||
| 122 | #define USE_SGTTY | 122 | #define USE_SGTTY |
| 123 | #endif | 123 | #endif |
| 124 | 124 | ||
| 125 | #ifdef WIN32 | 125 | #ifdef _WIN32 |
| 126 | #define USE_FTIME 1 | 126 | #define USE_FTIME 1 |
| 127 | #define USE_RENAME 1 | 127 | #define USE_RENAME 1 |
| 128 | #define NO_FCHMOD 1 | 128 | #define NO_FCHMOD 1 |
diff --git a/3rd_party/libsrp6a-sha512/t_misc.c b/3rd_party/libsrp6a-sha512/t_misc.c index 3a2cda1..34b9509 100644 --- a/3rd_party/libsrp6a-sha512/t_misc.c +++ b/3rd_party/libsrp6a-sha512/t_misc.c | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #include <sys/stat.h> | 38 | #include <sys/stat.h> |
| 39 | #include <fcntl.h> | 39 | #include <fcntl.h> |
| 40 | 40 | ||
| 41 | #ifdef WIN32 | 41 | #ifdef _WIN32 |
| 42 | #include <process.h> | 42 | #include <process.h> |
| 43 | #include <io.h> | 43 | #include <io.h> |
| 44 | #endif | 44 | #endif |
| @@ -77,7 +77,12 @@ SHA1_CTX randctxt; | |||
| 77 | * tricks with variable ordering and sometimes define quirky | 77 | * tricks with variable ordering and sometimes define quirky |
| 78 | * environment variables like $WINDOWID or $_. | 78 | * environment variables like $WINDOWID or $_. |
| 79 | */ | 79 | */ |
| 80 | #ifdef __APPLE__ | ||
| 81 | #include <crt_externs.h> | ||
| 82 | #define environ (*_NSGetEnviron()) | ||
| 83 | #else | ||
| 80 | extern char ** environ; | 84 | extern char ** environ; |
| 85 | #endif | ||
| 81 | 86 | ||
| 82 | static void | 87 | static void |
| 83 | t_envhash(unsigned char * out) | 88 | t_envhash(unsigned char * out) |
| @@ -207,7 +212,7 @@ t_initrand() | |||
| 207 | #if defined(OPENSSL) /* OpenSSL has nifty win32 entropy-gathering code */ | 212 | #if defined(OPENSSL) /* OpenSSL has nifty win32 entropy-gathering code */ |
| 208 | #if OPENSSL_VERSION_NUMBER >= 0x00905100 | 213 | #if OPENSSL_VERSION_NUMBER >= 0x00905100 |
| 209 | r = RAND_status(); | 214 | r = RAND_status(); |
| 210 | #if defined(WINDOWS) || defined(WIN32) | 215 | #if defined(WINDOWS) || defined(_WIN32) |
| 211 | if(r) /* Don't do the Unix-y stuff on Windows if possible */ | 216 | if(r) /* Don't do the Unix-y stuff on Windows if possible */ |
| 212 | return; | 217 | return; |
| 213 | #else | 218 | #else |
| @@ -220,7 +225,7 @@ t_initrand() | |||
| 220 | if(r > 0) { | 225 | if(r > 0) { |
| 221 | yarrow_add_entropy(entropy, r, &g_rng); | 226 | yarrow_add_entropy(entropy, r, &g_rng); |
| 222 | memset(entropy, 0, sizeof(entropy)); | 227 | memset(entropy, 0, sizeof(entropy)); |
| 223 | # if defined(WINDOWS) || defined(WIN32) | 228 | # if defined(WINDOWS) || defined(_WIN32) |
| 224 | /* Don't do the Unix-y stuff on Windows if possible */ | 229 | /* Don't do the Unix-y stuff on Windows if possible */ |
| 225 | yarrow_ready(&g_rng); | 230 | yarrow_ready(&g_rng); |
| 226 | return; | 231 | return; |
| @@ -228,13 +233,13 @@ t_initrand() | |||
| 228 | } | 233 | } |
| 229 | #endif | 234 | #endif |
| 230 | 235 | ||
| 231 | #if !defined(WINDOWS) && !defined(WIN32) | 236 | #if !defined(WINDOWS) && !defined(_WIN32) |
| 232 | i = open("/dev/urandom", O_RDONLY); | 237 | i = open("/dev/urandom", O_RDONLY); |
| 233 | if(i > 0) { | 238 | if(i > 0) { |
| 234 | r += read(i, preseed.devrand, sizeof(preseed.devrand)); | 239 | r += read(i, preseed.devrand, sizeof(preseed.devrand)); |
| 235 | close(i); | 240 | close(i); |
| 236 | } | 241 | } |
| 237 | #endif /* !WINDOWS && !WIN32 */ | 242 | #endif /* !WINDOWS && !_WIN32 */ |
| 238 | 243 | ||
| 239 | /* Resort to truerand only if desperate for some Real entropy */ | 244 | /* Resort to truerand only if desperate for some Real entropy */ |
| 240 | if(r == 0) | 245 | if(r == 0) |
| @@ -250,7 +255,7 @@ t_initrand() | |||
| 250 | preseed.subsec = t.tv_usec; | 255 | preseed.subsec = t.tv_usec; |
| 251 | #endif | 256 | #endif |
| 252 | preseed.pid = getpid(); | 257 | preseed.pid = getpid(); |
| 253 | #ifndef WIN32 | 258 | #ifndef _WIN32 |
| 254 | preseed.ppid = getppid(); | 259 | preseed.ppid = getppid(); |
| 255 | #endif | 260 | #endif |
| 256 | t_envhash(preseed.envh); | 261 | t_envhash(preseed.envh); |
diff --git a/3rd_party/libsrp6a-sha512/t_truerand.c b/3rd_party/libsrp6a-sha512/t_truerand.c index f995ed7..cd27d0d 100644 --- a/3rd_party/libsrp6a-sha512/t_truerand.c +++ b/3rd_party/libsrp6a-sha512/t_truerand.c | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | 54 | ||
| 55 | #include "t_defines.h" | 55 | #include "t_defines.h" |
| 56 | 56 | ||
| 57 | #ifdef WIN32 | 57 | #ifdef _WIN32 |
| 58 | 58 | ||
| 59 | # ifdef CRYPTOLIB | 59 | # ifdef CRYPTOLIB |
| 60 | 60 | ||
| @@ -69,7 +69,7 @@ raw_truerand() | |||
| 69 | return truerand(); | 69 | return truerand(); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | # else /* !CRYPTOLIB && WIN32 */ | 72 | # else /* !CRYPTOLIB && _WIN32 */ |
| 73 | 73 | ||
| 74 | #include <windows.h> | 74 | #include <windows.h> |
| 75 | #include <wtypes.h> | 75 | #include <wtypes.h> |
| @@ -128,7 +128,7 @@ raw_truerand() { | |||
| 128 | 128 | ||
| 129 | # endif /* CRYPTOLIB */ | 129 | # endif /* CRYPTOLIB */ |
| 130 | 130 | ||
| 131 | #else /* !WIN32 */ | 131 | #else /* !_WIN32 */ |
| 132 | 132 | ||
| 133 | #include <signal.h> | 133 | #include <signal.h> |
| 134 | #include <setjmp.h> | 134 | #include <setjmp.h> |
| @@ -238,4 +238,4 @@ raw_n_truerand(int n) | |||
| 238 | return v % n; | 238 | return v % n; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | #endif /* !CRYPTOLIB || !WIN32 */ | 241 | #endif /* !CRYPTOLIB || !_WIN32 */ |
diff --git a/Makefile.am b/Makefile.am index 352b28f..f429f2f 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -3,7 +3,6 @@ ACLOCAL_AMFLAGS = -I m4 | |||
| 3 | SUBDIRS = 3rd_party common src include $(CYTHON_SUB) tools docs | 3 | SUBDIRS = 3rd_party common src include $(CYTHON_SUB) tools docs |
| 4 | 4 | ||
| 5 | EXTRA_DIST = \ | 5 | EXTRA_DIST = \ |
| 6 | docs \ | ||
| 7 | README.md \ | 6 | README.md \ |
| 8 | git-version-gen | 7 | git-version-gen |
| 9 | 8 | ||
| @@ -1,3 +1,34 @@ | |||
| 1 | Version 1.4.0 | ||
| 2 | ~~~~~~~~~~~~~ | ||
| 3 | |||
| 4 | * Development release | ||
| 5 | - From now on, releases will be made more frequently | ||
| 6 | * Changes: | ||
| 7 | - Add support for MbedTLS | ||
| 8 | - Add Reverse Proxy implementation | ||
| 9 | - Add support for wireless pairing (AppleTV) | ||
| 10 | - Embed 3rd party libraries for ed25519 and SRP6a | ||
| 11 | - Fixes in idevicedebug | ||
| 12 | - idevicecrashreport: Allow filtering crash reports by filename | ||
| 13 | - Add idevicedevmodectl tool | ||
| 14 | - Fixes for idevicebackup2 | ||
| 15 | - Add property_list_client_get_service_client() and service_get_connection() functions | ||
| 16 | - Add idevicebtlogger | ||
| 17 | - Add new idevice_events_subscribe/unsubscribe API | ||
| 18 | - Move LIBIMOBILEDEVICE_API to public headers | ||
| 19 | - Add afc_strerror function | ||
| 20 | - Add libimobiledevice_version() function | ||
| 21 | - Use libimobiledevice-glue's SHA1 implementation | ||
| 22 | - Add support for iOS 17+ Personalized Developer Disk image mounting | ||
| 23 | - Fix compilation on MSVC | ||
| 24 | - Add idevice_strerror() to interface | ||
| 25 | - Add new idevice_get_device_version() to interface | ||
| 26 | - Add os_trace_relay service implementation | ||
| 27 | - Fixes for idevicesyslog | ||
| 28 | - afc: Add afc_get_file_info_plist and afc_get_device_info_plist functions | ||
| 29 | ... and several other internal changes | ||
| 30 | |||
| 31 | |||
| 1 | Version 1.3.0 | 32 | Version 1.3.0 |
| 2 | ~~~~~~~~~~~~~ | 33 | ~~~~~~~~~~~~~ |
| 3 | 34 | ||
| @@ -179,8 +179,8 @@ We are still working on the guidelines so bear with us! | |||
| 179 | ## Links | 179 | ## Links |
| 180 | 180 | ||
| 181 | * Homepage: https://libimobiledevice.org/ | 181 | * Homepage: https://libimobiledevice.org/ |
| 182 | * Repository: https://git.libimobiledevice.org/libimobiledevice.git | 182 | * Repository: https://github.com/libimobiledevice/libimobiledevice.git |
| 183 | * Repository (Mirror): https://github.com/libimobiledevice/libimobiledevice.git | 183 | * Repository (Mirror): https://git.libimobiledevice.org/libimobiledevice.git |
| 184 | * Issue Tracker: https://github.com/libimobiledevice/libimobiledevice/issues | 184 | * Issue Tracker: https://github.com/libimobiledevice/libimobiledevice/issues |
| 185 | * Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel | 185 | * Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel |
| 186 | * Twitter: https://twitter.com/libimobiledev | 186 | * Twitter: https://twitter.com/libimobiledev |
| @@ -198,4 +198,4 @@ iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc. | |||
| 198 | This project is an independent software and has not been authorized, sponsored, | 198 | This project is an independent software and has not been authorized, sponsored, |
| 199 | or otherwise approved by Apple Inc. | 199 | or otherwise approved by Apple Inc. |
| 200 | 200 | ||
| 201 | README Updated on: 2024-06-27 | 201 | README Updated on: 2024-10-22 |
diff --git a/common/debug.c b/common/debug.c index cf1bc2f..7a593fc 100644 --- a/common/debug.c +++ b/common/debug.c | |||
| @@ -30,6 +30,9 @@ | |||
| 30 | #include <stdint.h> | 30 | #include <stdint.h> |
| 31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
| 32 | #include <time.h> | 32 | #include <time.h> |
| 33 | #ifndef _WIN32 | ||
| 34 | #include <sys/time.h> | ||
| 35 | #endif | ||
| 33 | 36 | ||
| 34 | #include "src/idevice.h" | 37 | #include "src/idevice.h" |
| 35 | #include "debug.h" | 38 | #include "debug.h" |
| @@ -51,27 +54,31 @@ void internal_set_debug_level(int level) | |||
| 51 | #ifndef STRIP_DEBUG_CODE | 54 | #ifndef STRIP_DEBUG_CODE |
| 52 | static void debug_print_line(const char *func, const char *file, int line, const char *buffer) | 55 | static void debug_print_line(const char *func, const char *file, int line, const char *buffer) |
| 53 | { | 56 | { |
| 54 | char *str_time = NULL; | 57 | char str_time[24]; |
| 55 | char *header = NULL; | 58 | #ifdef _WIN32 |
| 59 | SYSTEMTIME lt; | ||
| 60 | GetLocalTime(<); | ||
| 61 | snprintf(str_time, 24, "%02d:%02d:%02d.%03d", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds); | ||
| 62 | #else | ||
| 63 | #ifdef HAVE_GETTIMEOFDAY | ||
| 64 | struct timeval tv; | ||
| 65 | struct tm *tp; | ||
| 66 | gettimeofday(&tv, NULL); | ||
| 67 | #ifdef HAVE_LOCALTIME_R | ||
| 68 | struct tm tp_; | ||
| 69 | tp = localtime_r(&tv.tv_sec, &tp_); | ||
| 70 | #else | ||
| 71 | tp = localtime(&tv.tv_sec); | ||
| 72 | #endif | ||
| 73 | strftime(str_time, 9, "%H:%M:%S", tp); | ||
| 74 | snprintf(str_time+8, 10, ".%03d", (int)tv.tv_usec/1000); | ||
| 75 | #else | ||
| 56 | time_t the_time; | 76 | time_t the_time; |
| 57 | |||
| 58 | time(&the_time); | 77 | time(&the_time); |
| 59 | str_time = (char*)malloc(255); | 78 | strftime(str_time, 15, "%H:%M:%S", localtime (&the_time)); |
| 60 | strftime(str_time, 254, "%H:%M:%S", localtime (&the_time)); | 79 | #endif |
| 61 | 80 | #endif | |
| 62 | /* generate header text */ | 81 | fprintf(stderr, "%s %s:%d %s(): %s\n", str_time, file, line, func, buffer); |
| 63 | if(asprintf(&header, "%s %s:%d %s()", str_time, file, line, func)<0){} | ||
| 64 | free (str_time); | ||
| 65 | |||
| 66 | /* trim ending newlines */ | ||
| 67 | |||
| 68 | /* print header */ | ||
| 69 | fprintf(stderr, "%s: ", header); | ||
| 70 | |||
| 71 | /* print actual debug content */ | ||
| 72 | fprintf(stderr, "%s\n", buffer); | ||
| 73 | |||
| 74 | free (header); | ||
| 75 | } | 82 | } |
| 76 | #endif | 83 | #endif |
| 77 | 84 | ||
diff --git a/common/userpref.c b/common/userpref.c index 48bcfcb..76945e1 100644 --- a/common/userpref.c +++ b/common/userpref.c | |||
| @@ -29,13 +29,18 @@ | |||
| 29 | #include <stdint.h> | 29 | #include <stdint.h> |
| 30 | #include <stdlib.h> | 30 | #include <stdlib.h> |
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <errno.h> | ||
| 33 | |||
| 32 | #ifdef HAVE_SYS_TYPES_H | 34 | #ifdef HAVE_SYS_TYPES_H |
| 33 | #include <sys/types.h> | 35 | #include <sys/types.h> |
| 34 | #endif | 36 | #endif |
| 35 | #ifndef WIN32 | 37 | #include <dirent.h> |
| 38 | #ifndef _WIN32 | ||
| 36 | #include <pwd.h> | 39 | #include <pwd.h> |
| 37 | #endif | ||
| 38 | #include <unistd.h> | 40 | #include <unistd.h> |
| 41 | #include <libgen.h> | ||
| 42 | #include <sys/stat.h> | ||
| 43 | #endif | ||
| 39 | #include <usbmuxd.h> | 44 | #include <usbmuxd.h> |
| 40 | #if defined(HAVE_OPENSSL) | 45 | #if defined(HAVE_OPENSSL) |
| 41 | #include <openssl/bn.h> | 46 | #include <openssl/bn.h> |
| @@ -64,12 +69,7 @@ | |||
| 64 | #error No supported TLS/SSL library enabled | 69 | #error No supported TLS/SSL library enabled |
| 65 | #endif | 70 | #endif |
| 66 | 71 | ||
| 67 | #include <dirent.h> | 72 | #ifdef _WIN32 |
| 68 | #include <libgen.h> | ||
| 69 | #include <sys/stat.h> | ||
| 70 | #include <errno.h> | ||
| 71 | |||
| 72 | #ifdef WIN32 | ||
| 73 | #include <shlobj.h> | 73 | #include <shlobj.h> |
| 74 | #endif | 74 | #endif |
| 75 | 75 | ||
| @@ -77,6 +77,7 @@ | |||
| 77 | #define ETIMEDOUT 138 | 77 | #define ETIMEDOUT 138 |
| 78 | #endif | 78 | #endif |
| 79 | 79 | ||
| 80 | #include <libimobiledevice/libimobiledevice.h> | ||
| 80 | #include <libimobiledevice-glue/utils.h> | 81 | #include <libimobiledevice-glue/utils.h> |
| 81 | 82 | ||
| 82 | #include "userpref.h" | 83 | #include "userpref.h" |
| @@ -93,7 +94,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | |||
| 93 | }; | 94 | }; |
| 94 | #endif | 95 | #endif |
| 95 | 96 | ||
| 96 | #ifdef WIN32 | 97 | #ifdef _WIN32 |
| 97 | #define DIR_SEP '\\' | 98 | #define DIR_SEP '\\' |
| 98 | #define DIR_SEP_S "\\" | 99 | #define DIR_SEP_S "\\" |
| 99 | #else | 100 | #else |
| @@ -103,7 +104,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | |||
| 103 | 104 | ||
| 104 | #define USERPREF_CONFIG_EXTENSION ".plist" | 105 | #define USERPREF_CONFIG_EXTENSION ".plist" |
| 105 | 106 | ||
| 106 | #ifdef WIN32 | 107 | #ifdef _WIN32 |
| 107 | #define USERPREF_CONFIG_DIR "Apple"DIR_SEP_S"Lockdown" | 108 | #define USERPREF_CONFIG_DIR "Apple"DIR_SEP_S"Lockdown" |
| 108 | #else | 109 | #else |
| 109 | #define USERPREF_CONFIG_DIR "lockdown" | 110 | #define USERPREF_CONFIG_DIR "lockdown" |
| @@ -113,7 +114,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | |||
| 113 | 114 | ||
| 114 | static char *__config_dir = NULL; | 115 | static char *__config_dir = NULL; |
| 115 | 116 | ||
| 116 | #ifdef WIN32 | 117 | #ifdef _WIN32 |
| 117 | static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written) | 118 | static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written) |
| 118 | { | 119 | { |
| 119 | if (!unistr || (len <= 0)) return NULL; | 120 | if (!unistr || (len <= 0)) return NULL; |
| @@ -155,7 +156,7 @@ const char *userpref_get_config_dir() | |||
| 155 | if (__config_dir) | 156 | if (__config_dir) |
| 156 | return __config_dir; | 157 | return __config_dir; |
| 157 | 158 | ||
| 158 | #ifdef WIN32 | 159 | #ifdef _WIN32 |
| 159 | wchar_t path[MAX_PATH+1]; | 160 | wchar_t path[MAX_PATH+1]; |
| 160 | HRESULT hr; | 161 | HRESULT hr; |
| 161 | LPITEMIDLIST pidl = NULL; | 162 | LPITEMIDLIST pidl = NULL; |
| @@ -419,7 +420,7 @@ static int _mbedtls_x509write_crt_set_basic_constraints_critical(mbedtls_x509wri | |||
| 419 | * | 420 | * |
| 420 | * @return 1 if keys were successfully generated, 0 otherwise | 421 | * @return 1 if keys were successfully generated, 0 otherwise |
| 421 | */ | 422 | */ |
| 422 | userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key) | 423 | userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key, unsigned int device_version) |
| 423 | { | 424 | { |
| 424 | userpref_error_t ret = USERPREF_E_SSL_ERROR; | 425 | userpref_error_t ret = USERPREF_E_SSL_ERROR; |
| 425 | 426 | ||
| @@ -484,7 +485,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 484 | X509_set_pubkey(root_cert, root_pkey); | 485 | X509_set_pubkey(root_cert, root_pkey); |
| 485 | 486 | ||
| 486 | /* sign root cert with root private key */ | 487 | /* sign root cert with root private key */ |
| 487 | X509_sign(root_cert, root_pkey, EVP_sha1()); | 488 | X509_sign(root_cert, root_pkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? EVP_sha1() : EVP_sha256()); |
| 488 | } | 489 | } |
| 489 | 490 | ||
| 490 | /* create host certificate */ | 491 | /* create host certificate */ |
| @@ -517,7 +518,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 517 | X509_set_pubkey(host_cert, host_pkey); | 518 | X509_set_pubkey(host_cert, host_pkey); |
| 518 | 519 | ||
| 519 | /* sign host cert with root private key */ | 520 | /* sign host cert with root private key */ |
| 520 | X509_sign(host_cert, root_pkey, EVP_sha1()); | 521 | X509_sign(host_cert, root_pkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? EVP_sha1() : EVP_sha256()); |
| 521 | } | 522 | } |
| 522 | 523 | ||
| 523 | if (root_cert && root_pkey && host_cert && host_pkey) { | 524 | if (root_cert && root_pkey && host_cert && host_pkey) { |
| @@ -609,7 +610,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 609 | X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment"); | 610 | X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment"); |
| 610 | 611 | ||
| 611 | /* sign device certificate with root private key */ | 612 | /* sign device certificate with root private key */ |
| 612 | if (X509_sign(dev_cert, root_pkey, EVP_sha1())) { | 613 | if (X509_sign(dev_cert, root_pkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? EVP_sha1() : EVP_sha256())) { |
| 613 | /* if signing succeeded, export in PEM format */ | 614 | /* if signing succeeded, export in PEM format */ |
| 614 | BIO* membp = BIO_new(BIO_s_mem()); | 615 | BIO* membp = BIO_new(BIO_s_mem()); |
| 615 | if (PEM_write_bio_X509(membp, dev_cert) > 0) { | 616 | if (PEM_write_bio_X509(membp, dev_cert) > 0) { |
| @@ -661,7 +662,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 661 | gnutls_x509_crt_set_ca_status(root_cert, 1); | 662 | gnutls_x509_crt_set_ca_status(root_cert, 1); |
| 662 | gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); | 663 | gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); |
| 663 | gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); | 664 | gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); |
| 664 | gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); | 665 | gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256, 0); |
| 665 | 666 | ||
| 666 | gnutls_x509_crt_set_key(host_cert, host_privkey); | 667 | gnutls_x509_crt_set_key(host_cert, host_privkey); |
| 667 | gnutls_x509_crt_set_serial(host_cert, "\x01", 1); | 668 | gnutls_x509_crt_set_serial(host_cert, "\x01", 1); |
| @@ -670,7 +671,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 670 | gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); | 671 | gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); |
| 671 | gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); | 672 | gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); |
| 672 | gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); | 673 | gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); |
| 673 | gnutls_x509_crt_sign2(host_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); | 674 | gnutls_x509_crt_sign2(host_cert, root_cert, root_privkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256, 0); |
| 674 | 675 | ||
| 675 | /* export to PEM format */ | 676 | /* export to PEM format */ |
| 676 | size_t root_key_export_size = 0; | 677 | size_t root_key_export_size = 0; |
| @@ -768,17 +769,17 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 768 | gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); | 769 | gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); |
| 769 | 770 | ||
| 770 | /* use custom hash generation for compatibility with the "Apple ecosystem" */ | 771 | /* use custom hash generation for compatibility with the "Apple ecosystem" */ |
| 771 | const gnutls_digest_algorithm_t dig_sha1 = GNUTLS_DIG_SHA1; | 772 | const gnutls_digest_algorithm_t dig_sha = (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256; |
| 772 | size_t hash_size = gnutls_hash_get_len(dig_sha1); | 773 | size_t hash_size = gnutls_hash_get_len(dig_sha); |
| 773 | unsigned char hash[hash_size]; | 774 | unsigned char hash[hash_size]; |
| 774 | if (gnutls_hash_fast(dig_sha1, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) { | 775 | if (gnutls_hash_fast(dig_sha, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) { |
| 775 | debug_info("ERROR: Failed to generate SHA1 for public key"); | 776 | debug_info("ERROR: Failed to generate SHA for public key"); |
| 776 | } else { | 777 | } else { |
| 777 | gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size); | 778 | gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size); |
| 778 | } | 779 | } |
| 779 | 780 | ||
| 780 | gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); | 781 | gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); |
| 781 | gnutls_error = gnutls_x509_crt_sign2(dev_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); | 782 | gnutls_error = gnutls_x509_crt_sign2(dev_cert, root_cert, root_privkey, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256, 0); |
| 782 | if (GNUTLS_E_SUCCESS == gnutls_error) { | 783 | if (GNUTLS_E_SUCCESS == gnutls_error) { |
| 783 | /* if everything went well, export in PEM format */ | 784 | /* if everything went well, export in PEM format */ |
| 784 | size_t export_size = 0; | 785 | size_t export_size = 0; |
| @@ -872,7 +873,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 872 | 873 | ||
| 873 | /* sign root cert with root private key */ | 874 | /* sign root cert with root private key */ |
| 874 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); | 875 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); |
| 875 | mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1); | 876 | mbedtls_x509write_crt_set_md_alg(&cert, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? MBEDTLS_MD_SHA1 : MBEDTLS_MD_SHA256); |
| 876 | 877 | ||
| 877 | unsigned char outbuf[16384]; | 878 | unsigned char outbuf[16384]; |
| 878 | 879 | ||
| @@ -931,7 +932,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 931 | 932 | ||
| 932 | /* sign host cert with root private key */ | 933 | /* sign host cert with root private key */ |
| 933 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); | 934 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); |
| 934 | mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1); | 935 | mbedtls_x509write_crt_set_md_alg(&cert, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? MBEDTLS_MD_SHA1 : MBEDTLS_MD_SHA256); |
| 935 | 936 | ||
| 936 | /* write host private key */ | 937 | /* write host private key */ |
| 937 | mbedtls_pk_write_key_pem(&host_pkey, outbuf, sizeof(outbuf)); | 938 | mbedtls_pk_write_key_pem(&host_pkey, outbuf, sizeof(outbuf)); |
| @@ -991,7 +992,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da | |||
| 991 | 992 | ||
| 992 | /* sign device certificate with root private key */ | 993 | /* sign device certificate with root private key */ |
| 993 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); | 994 | mbedtls_x509write_crt_set_issuer_key(&cert, &root_pkey); |
| 994 | mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA1); | 995 | mbedtls_x509write_crt_set_md_alg(&cert, (device_version < IDEVICE_DEVICE_VERSION(4,0,0)) ? MBEDTLS_MD_SHA1 : MBEDTLS_MD_SHA256); |
| 995 | 996 | ||
| 996 | /* write device certificate */ | 997 | /* write device certificate */ |
| 997 | mbedtls_x509write_crt_pem(&cert, outbuf, sizeof(outbuf), mbedtls_ctr_drbg_random, &ctr_drbg); | 998 | mbedtls_x509write_crt_pem(&cert, outbuf, sizeof(outbuf), mbedtls_ctr_drbg_random, &ctr_drbg); |
diff --git a/common/userpref.h b/common/userpref.h index 75bb8b7..9a1832c 100644 --- a/common/userpref.h +++ b/common/userpref.h | |||
| @@ -68,7 +68,7 @@ userpref_error_t userpref_read_pair_record(const char *udid, plist_t *pair_recor | |||
| 68 | userpref_error_t userpref_save_pair_record(const char *udid, uint32_t device_id, plist_t pair_record); | 68 | userpref_error_t userpref_save_pair_record(const char *udid, uint32_t device_id, plist_t pair_record); |
| 69 | userpref_error_t userpref_delete_pair_record(const char *udid); | 69 | userpref_error_t userpref_delete_pair_record(const char *udid); |
| 70 | 70 | ||
| 71 | userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key); | 71 | userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key, unsigned int device_version); |
| 72 | #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS) | 72 | #if defined(HAVE_OPENSSL) || defined(HAVE_MBEDTLS) |
| 73 | userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, key_data_t* key); | 73 | userpref_error_t pair_record_import_key_with_name(plist_t pair_record, const char* name, key_data_t* key); |
| 74 | userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, key_data_t* cert); | 74 | userpref_error_t pair_record_import_crt_with_name(plist_t pair_record, const char* name, key_data_t* cert); |
diff --git a/configure.ac b/configure.ac index c67e896..055fe04 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -15,7 +15,7 @@ dnl libtool versioning | |||
| 15 | # changes to the signature and the semantic) | 15 | # changes to the signature and the semantic) |
| 16 | # ? :+1 : ? == just internal changes | 16 | # ? :+1 : ? == just internal changes |
| 17 | # CURRENT : REVISION : AGE | 17 | # CURRENT : REVISION : AGE |
| 18 | LIBIMOBILEDEVICE_SO_VERSION=6:0:0 | 18 | LIBIMOBILEDEVICE_SO_VERSION=7:0:1 |
| 19 | 19 | ||
| 20 | AC_SUBST(LIBIMOBILEDEVICE_SO_VERSION) | 20 | AC_SUBST(LIBIMOBILEDEVICE_SO_VERSION) |
| 21 | 21 | ||
| @@ -70,7 +70,7 @@ AC_TYPE_UINT32_T | |||
| 70 | AC_TYPE_UINT8_T | 70 | AC_TYPE_UINT8_T |
| 71 | 71 | ||
| 72 | # Checks for library functions. | 72 | # Checks for library functions. |
| 73 | AC_CHECK_FUNCS([asprintf strcasecmp strdup strerror strndup stpcpy vasprintf getifaddrs]) | 73 | AC_CHECK_FUNCS([asprintf strcasecmp strdup strerror strndup stpcpy vasprintf getifaddrs gettimeofday localtime_r]) |
| 74 | 74 | ||
| 75 | AC_CHECK_HEADER(endian.h, [ac_cv_have_endian_h="yes"], [ac_cv_have_endian_h="no"]) | 75 | AC_CHECK_HEADER(endian.h, [ac_cv_have_endian_h="yes"], [ac_cv_have_endian_h="no"]) |
| 76 | if test "x$ac_cv_have_endian_h" = "xno"; then | 76 | if test "x$ac_cv_have_endian_h" = "xno"; then |
| @@ -84,8 +84,24 @@ if test "x$ac_cv_have_endian_h" = "xno"; then | |||
| 84 | fi | 84 | fi |
| 85 | fi | 85 | fi |
| 86 | 86 | ||
| 87 | CACHED_CFLAGS="$CFLAGS" | ||
| 88 | CFLAGS+=" $libplist_CFLAGS -Werror" | ||
| 89 | |||
| 87 | AC_CHECK_DECL([plist_from_json], [AC_DEFINE([HAVE_PLIST_JSON], [1], [Define if libplist has JSON support])], [], [[#include <plist/plist.h>]]) | 90 | AC_CHECK_DECL([plist_from_json], [AC_DEFINE([HAVE_PLIST_JSON], [1], [Define if libplist has JSON support])], [], [[#include <plist/plist.h>]]) |
| 88 | 91 | ||
| 92 | # check if libplist has plist_new_unix_date() | ||
| 93 | AC_CACHE_CHECK(for plist_new_unix_date, ac_cv_plist_unix_date, | ||
| 94 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | ||
| 95 | #include <plist/plist.h> | ||
| 96 | ]], [[ | ||
| 97 | return plist_new_unix_date(0) ? 0 : 1 | ||
| 98 | ]])],[ac_cv_plist_unix_date=yes],[ac_cv_plist_unix_date=no])) | ||
| 99 | if test "$ac_cv_plist_unix_date" = "yes"; then | ||
| 100 | AC_DEFINE(HAVE_PLIST_UNIX_DATE, 1, [Define if libplist has new unix date API (>= 2.7.0)]) | ||
| 101 | fi | ||
| 102 | |||
| 103 | CFLAGS="$CACHED_CFLAGS" | ||
| 104 | |||
| 89 | # Check for operating system | 105 | # Check for operating system |
| 90 | AC_MSG_CHECKING([for platform-specific build settings]) | 106 | AC_MSG_CHECKING([for platform-specific build settings]) |
| 91 | case ${host_os} in | 107 | case ${host_os} in |
| @@ -93,6 +109,7 @@ case ${host_os} in | |||
| 93 | AC_MSG_RESULT([${host_os}]) | 109 | AC_MSG_RESULT([${host_os}]) |
| 94 | win32=true | 110 | win32=true |
| 95 | AC_DEFINE(WINVER, 0x0501, [minimum Windows version]) | 111 | AC_DEFINE(WINVER, 0x0501, [minimum Windows version]) |
| 112 | deplibs_check_method='pass_all' | ||
| 96 | ;; | 113 | ;; |
| 97 | darwin*) | 114 | darwin*) |
| 98 | AC_MSG_RESULT([${host_os}]) | 115 | AC_MSG_RESULT([${host_os}]) |
| @@ -107,24 +124,6 @@ esac | |||
| 107 | AM_CONDITIONAL(WIN32, test x$win32 = xtrue) | 124 | AM_CONDITIONAL(WIN32, test x$win32 = xtrue) |
| 108 | AM_CONDITIONAL(DARWIN, test x$darwin = xtrue) | 125 | AM_CONDITIONAL(DARWIN, test x$darwin = xtrue) |
| 109 | 126 | ||
| 110 | # Check if the C compiler supports __attribute__((constructor)) | ||
| 111 | AC_CACHE_CHECK([wether the C compiler supports constructor/destructor attributes], | ||
| 112 | ac_cv_attribute_constructor, [ | ||
| 113 | ac_cv_attribute_constructor=no | ||
| 114 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM( | ||
| 115 | [[ | ||
| 116 | static void __attribute__((constructor)) test_constructor(void) { | ||
| 117 | } | ||
| 118 | static void __attribute__((destructor)) test_destructor(void) { | ||
| 119 | } | ||
| 120 | ]], [])], | ||
| 121 | [ac_cv_attribute_constructor=yes] | ||
| 122 | )] | ||
| 123 | ) | ||
| 124 | if test "$ac_cv_attribute_constructor" = "yes"; then | ||
| 125 | AC_DEFINE(HAVE_ATTRIBUTE_CONSTRUCTOR, 1, [Define if the C compiler supports constructor/destructor attributes]) | ||
| 126 | fi | ||
| 127 | |||
| 128 | AC_CHECK_MEMBER(struct dirent.d_type, AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [define if struct dirent has member d_type]),, [#include <dirent.h>]) | 127 | AC_CHECK_MEMBER(struct dirent.d_type, AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [define if struct dirent has member d_type]),, [#include <dirent.h>]) |
| 129 | 128 | ||
| 130 | # Cython Python Bindings | 129 | # Cython Python Bindings |
diff --git a/cython/debugserver.pxi b/cython/debugserver.pxi index a3b7d1e..fb96320 100644 --- a/cython/debugserver.pxi +++ b/cython/debugserver.pxi | |||
| @@ -43,13 +43,7 @@ cdef class DebugServerError(BaseError): | |||
| 43 | BaseError.__init__(self, *args, **kwargs) | 43 | BaseError.__init__(self, *args, **kwargs) |
| 44 | 44 | ||
| 45 | 45 | ||
| 46 | # from http://stackoverflow.com/a/17511714 | 46 | from cpython.bytes cimport PyBytes_AsString as PyString_AsString |
| 47 | # https://github.com/libimobiledevice/libimobiledevice/pull/198 | ||
| 48 | from cpython cimport PY_MAJOR_VERSION | ||
| 49 | if PY_MAJOR_VERSION <= 2: | ||
| 50 | from cpython.string cimport PyString_AsString | ||
| 51 | else: | ||
| 52 | from cpython.bytes cimport PyBytes_AsString as PyString_AsString | ||
| 53 | cdef char ** to_cstring_array(list_str): | 47 | cdef char ** to_cstring_array(list_str): |
| 54 | if not list_str: | 48 | if not list_str: |
| 55 | return NULL | 49 | return NULL |
diff --git a/docs/Makefile.am b/docs/Makefile.am index 8156d4f..c9b742f 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am | |||
| @@ -21,6 +21,7 @@ man_MANS = \ | |||
| 21 | idevicesetlocation.1 \ | 21 | idevicesetlocation.1 \ |
| 22 | afcclient.1 | 22 | afcclient.1 |
| 23 | 23 | ||
| 24 | EXTRA_DIST = $(man_MANS) | 24 | EXTRA_DIST = $(man_MANS) \ |
| 25 | doxygen | ||
| 25 | 26 | ||
| 26 | DISTCLEANFILES = html/* html | 27 | DISTCLEANFILES = html/* html |
diff --git a/docs/doxygen/custom.css b/docs/doxygen/custom.css index 62183bf..e9f1ea8 100644 --- a/docs/doxygen/custom.css +++ b/docs/doxygen/custom.css | |||
| @@ -230,6 +230,7 @@ div.fragment { | |||
| 230 | border: solid 1px rgb(221, 221, 221); | 230 | border: solid 1px rgb(221, 221, 221); |
| 231 | border-radius: 3px; | 231 | border-radius: 3px; |
| 232 | background-color: rgb(248, 248, 248); | 232 | background-color: rgb(248, 248, 248); |
| 233 | color: rgb(0,0,0); | ||
| 233 | } | 234 | } |
| 234 | 235 | ||
| 235 | div.line { | 236 | div.line { |
| @@ -1719,4 +1720,4 @@ th.markdownTableHeadNone { | |||
| 1719 | #projectnumber { | 1720 | #projectnumber { |
| 1720 | font-size: 0.75rem; | 1721 | font-size: 0.75rem; |
| 1721 | } | 1722 | } |
| 1722 | } \ No newline at end of file | 1723 | } |
diff --git a/docs/idevicecrashreport.1 b/docs/idevicecrashreport.1 index 6acd6e9..f117c87 100644 --- a/docs/idevicecrashreport.1 +++ b/docs/idevicecrashreport.1 | |||
| @@ -16,28 +16,31 @@ the device to the target DIRECTORY. | |||
| 16 | .SH OPTIONS | 16 | .SH OPTIONS |
| 17 | .TP | 17 | .TP |
| 18 | .B \-u, \-\-udid UDID | 18 | .B \-u, \-\-udid UDID |
| 19 | target specific device by UDID. | 19 | Target specific device by UDID. |
| 20 | .TP | 20 | .TP |
| 21 | .B \-n, \-\-network | 21 | .B \-n, \-\-network |
| 22 | connect to network device. | 22 | Connect to network device. |
| 23 | .TP | 23 | .TP |
| 24 | .B \-e, \-\-extract | 24 | .B \-e, \-\-extract |
| 25 | extract raw crash report into separate '.crash' files. | 25 | Extract raw crash report into separate '.crash' files. |
| 26 | .TP | 26 | .TP |
| 27 | .B \-k, \-\-keep | 27 | .B \-k, \-\-keep |
| 28 | copy but do not remove crash reports from device. | 28 | Copy but do not remove crash reports from device. |
| 29 | .TP | 29 | .TP |
| 30 | .B \-d, \-\-debug | 30 | .B \-d, \-\-debug |
| 31 | enable communication debugging. | 31 | Enable communication debugging. |
| 32 | .TP | 32 | .TP |
| 33 | .B \-f, \-\-filter NAME | 33 | .B \-f, \-\-filter NAME |
| 34 | filter crash reports by NAME (case sensitive) | 34 | Filter crash reports by NAME (case sensitive) |
| 35 | .TP | ||
| 36 | .B \-\-remove\-all | ||
| 37 | Remove all crash log files without copying. Can be used with \f[B]-f\f[] to only remove matching files. | ||
| 35 | .TP | 38 | .TP |
| 36 | .B \-h, \-\-help | 39 | .B \-h, \-\-help |
| 37 | prints usage information. | 40 | Prints usage information. |
| 38 | .TP | 41 | .TP |
| 39 | .B \-v, \-\-version | 42 | .B \-v, \-\-version |
| 40 | prints version information. | 43 | Prints version information. |
| 41 | 44 | ||
| 42 | .SH AUTHOR | 45 | .SH AUTHOR |
| 43 | Martin Szulecki | 46 | Martin Szulecki |
diff --git a/docs/idevicenotificationproxy.1 b/docs/idevicenotificationproxy.1 index 56dd0b0..627ee5d 100644 --- a/docs/idevicenotificationproxy.1 +++ b/docs/idevicenotificationproxy.1 | |||
| @@ -12,19 +12,22 @@ Post or observe notifications on an iOS device from the command line. | |||
| 12 | .SH OPTIONS | 12 | .SH OPTIONS |
| 13 | .TP | 13 | .TP |
| 14 | .B \-u, \-\-udid UDID | 14 | .B \-u, \-\-udid UDID |
| 15 | target specific device by UDID. | 15 | Target specific device by UDID. |
| 16 | .TP | ||
| 17 | .B \-i, \-\-insecure | ||
| 18 | Connect to insecure notification proxy (for non-paired devices). | ||
| 16 | .TP | 19 | .TP |
| 17 | .B \-n, \-\-network | 20 | .B \-n, \-\-network |
| 18 | connect to network device. | 21 | Connect to network device. |
| 19 | .TP | 22 | .TP |
| 20 | .B \-d, \-\-debug | 23 | .B \-d, \-\-debug |
| 21 | enable communication debugging. | 24 | Enable communication debugging. |
| 22 | .TP | 25 | .TP |
| 23 | .B \-h, \-\-help | 26 | .B \-h, \-\-help |
| 24 | prints usage information. | 27 | Prints usage information. |
| 25 | .TP | 28 | .TP |
| 26 | .B \-v, \-\-version | 29 | .B \-v, \-\-version |
| 27 | prints version information. | 30 | Prints version information. |
| 28 | 31 | ||
| 29 | .SH COMMANDS | 32 | .SH COMMANDS |
| 30 | .TP | 33 | .TP |
| @@ -38,6 +41,8 @@ observe notification IDs in the foreground until CTRL+C or signal is received. | |||
| 38 | 41 | ||
| 39 | Martin Szulecki | 42 | Martin Szulecki |
| 40 | 43 | ||
| 44 | Nikias Bassen | ||
| 45 | |||
| 41 | .SH ON THE WEB | 46 | .SH ON THE WEB |
| 42 | https://libimobiledevice.org | 47 | https://libimobiledevice.org |
| 43 | 48 | ||
diff --git a/docs/idevicesyslog.1 b/docs/idevicesyslog.1 index 66ae2e4..5a677b6 100644 --- a/docs/idevicesyslog.1 +++ b/docs/idevicesyslog.1 | |||
| @@ -38,13 +38,45 @@ If FILE already exists, it will be overwritten without warning. | |||
| 38 | .TP | 38 | .TP |
| 39 | .B \-\-colors | 39 | .B \-\-colors |
| 40 | Force writing colored output, e.g. when using \f[B]\-\-output\f[]. | 40 | Force writing colored output, e.g. when using \f[B]\-\-output\f[]. |
| 41 | .TP | ||
| 42 | .B \-\-syslog\-relay | ||
| 43 | Use old syslog_relay service instead of os_trace_relay (iOS 9+). | ||
| 44 | |||
| 45 | .SH COMMANDS | ||
| 46 | .TP | ||
| 47 | .B pidlist | ||
| 48 | Print a list with PID and name of all processes currently running on the device. | ||
| 49 | .TP | ||
| 50 | .B archive PATH | ||
| 51 | Request a logarchive from the device. It will be written in tar format to PATH. To pipe to another process use \- as PATH. | ||
| 52 | Below are some options to restrict the log message data. | ||
| 53 | |||
| 54 | In order to view the logarchive in a compatible log viewer, you can pipe the output data to \f[B]tar\f[] and have it extract into a new directory: | ||
| 55 | |||
| 56 | \f[B]mkdir test.logarchive && tools/idevicesyslog archive - |tar -C test.logarchive -xv\f[] | ||
| 57 | |||
| 58 | This will also print the filenames while they are extracted. | ||
| 59 | .TP | ||
| 60 | Further options for \f[B]archive\f[]: | ||
| 61 | .TP | ||
| 62 | .B \-\-start\-time VALUE | ||
| 63 | Start time of the log data as UNIX timestamp. Earlier messages will be dropped. | ||
| 64 | .TP | ||
| 65 | .B \-\-age\-limit VALUE | ||
| 66 | Maximum age of the log data, supposedly number of days. | ||
| 67 | .TP | ||
| 68 | .B \-\-size\-limit VALUE | ||
| 69 | Limit the size of the archive. The unit is currently unknown, so feel free to experiment. | ||
| 70 | .TP | ||
| 71 | Keep in mind that the device usually only has a backlog of a few minutes so the options might not have the desired effect. This is not a bug. | ||
| 41 | 72 | ||
| 42 | .SH FILTER OPTIONS | 73 | .SH FILTER OPTIONS |
| 43 | .TP | 74 | .TP |
| 44 | .B \-m, \-\-match STRING | 75 | .B \-m, \-\-match STRING |
| 45 | only print messages that contain STRING | 76 | only print messages that contain STRING |
| 46 | 77 | .TP | |
| 47 | This option will set a filter to only printed log messages that contain the given string. | 78 | .B \-M, \-\-unmatch STRING |
| 79 | print messages that do not contain STRING | ||
| 48 | .TP | 80 | .TP |
| 49 | .B \-t, \-\-trigger STRING | 81 | .B \-t, \-\-trigger STRING |
| 50 | start logging when matching STRING | 82 | start logging when matching STRING |
diff --git a/doxygen.cfg.in b/doxygen.cfg.in index 4cbbb2d..7bc1160 100644 --- a/doxygen.cfg.in +++ b/doxygen.cfg.in | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Doxyfile 1.8.16 | 1 | # Doxyfile 1.11.0 |
| 2 | 2 | ||
| 3 | # This file describes the settings to be used by the documentation system | 3 | # This file describes the settings to be used by the documentation system |
| 4 | # doxygen (www.doxygen.org) for a project. | 4 | # doxygen (www.doxygen.org) for a project. |
| @@ -12,6 +12,16 @@ | |||
| 12 | # For lists, items can also be appended using: | 12 | # For lists, items can also be appended using: |
| 13 | # TAG += value [value, ...] | 13 | # TAG += value [value, ...] |
| 14 | # Values that contain spaces should be placed between quotes (\" \"). | 14 | # Values that contain spaces should be placed between quotes (\" \"). |
| 15 | # | ||
| 16 | # Note: | ||
| 17 | # | ||
| 18 | # Use doxygen to compare the used configuration file with the template | ||
| 19 | # configuration file: | ||
| 20 | # doxygen -x [configFile] | ||
| 21 | # Use doxygen to compare the used configuration file with the template | ||
| 22 | # configuration file without replacing the environment variables or CMake type | ||
| 23 | # replacement variables: | ||
| 24 | # doxygen -x_noenv [configFile] | ||
| 15 | 25 | ||
| 16 | #--------------------------------------------------------------------------- | 26 | #--------------------------------------------------------------------------- |
| 17 | # Project related configuration options | 27 | # Project related configuration options |
| @@ -53,6 +63,12 @@ PROJECT_BRIEF = "API Documentation" | |||
| 53 | 63 | ||
| 54 | PROJECT_LOGO = docs/doxygen/logo-vector-clean.svg | 64 | PROJECT_LOGO = docs/doxygen/logo-vector-clean.svg |
| 55 | 65 | ||
| 66 | # With the PROJECT_ICON tag one can specify an icon that is included in the tabs | ||
| 67 | # when the HTML document is shown. Doxygen will copy the logo to the output | ||
| 68 | # directory. | ||
| 69 | |||
| 70 | PROJECT_ICON = | ||
| 71 | |||
| 56 | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path | 72 | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path |
| 57 | # into which the generated documentation will be written. If a relative path is | 73 | # into which the generated documentation will be written. If a relative path is |
| 58 | # entered, it will be relative to the location where doxygen was started. If | 74 | # entered, it will be relative to the location where doxygen was started. If |
| @@ -60,16 +76,28 @@ PROJECT_LOGO = docs/doxygen/logo-vector-clean.svg | |||
| 60 | 76 | ||
| 61 | OUTPUT_DIRECTORY = docs | 77 | OUTPUT_DIRECTORY = docs |
| 62 | 78 | ||
| 63 | # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- | 79 | # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 |
| 64 | # directories (in 2 levels) under the output directory of each output format and | 80 | # sub-directories (in 2 levels) under the output directory of each output format |
| 65 | # will distribute the generated files over these directories. Enabling this | 81 | # and will distribute the generated files over these directories. Enabling this |
| 66 | # option can be useful when feeding doxygen a huge amount of source files, where | 82 | # option can be useful when feeding doxygen a huge amount of source files, where |
| 67 | # putting all generated files in the same directory would otherwise causes | 83 | # putting all generated files in the same directory would otherwise causes |
| 68 | # performance problems for the file system. | 84 | # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to |
| 85 | # control the number of sub-directories. | ||
| 69 | # The default value is: NO. | 86 | # The default value is: NO. |
| 70 | 87 | ||
| 71 | CREATE_SUBDIRS = NO | 88 | CREATE_SUBDIRS = NO |
| 72 | 89 | ||
| 90 | # Controls the number of sub-directories that will be created when | ||
| 91 | # CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every | ||
| 92 | # level increment doubles the number of directories, resulting in 4096 | ||
| 93 | # directories at level 8 which is the default and also the maximum value. The | ||
| 94 | # sub-directories are organized in 2 levels, the first level always has a fixed | ||
| 95 | # number of 16 directories. | ||
| 96 | # Minimum value: 0, maximum value: 8, default value: 8. | ||
| 97 | # This tag requires that the tag CREATE_SUBDIRS is set to YES. | ||
| 98 | |||
| 99 | CREATE_SUBDIRS_LEVEL = 8 | ||
| 100 | |||
| 73 | # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII | 101 | # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII |
| 74 | # characters to appear in the names of generated files. If set to NO, non-ASCII | 102 | # characters to appear in the names of generated files. If set to NO, non-ASCII |
| 75 | # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode | 103 | # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode |
| @@ -81,14 +109,14 @@ ALLOW_UNICODE_NAMES = NO | |||
| 81 | # The OUTPUT_LANGUAGE tag is used to specify the language in which all | 109 | # The OUTPUT_LANGUAGE tag is used to specify the language in which all |
| 82 | # documentation generated by doxygen is written. Doxygen will use this | 110 | # documentation generated by doxygen is written. Doxygen will use this |
| 83 | # information to generate all constant output in the proper language. | 111 | # information to generate all constant output in the proper language. |
| 84 | # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, | 112 | # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, |
| 85 | # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), | 113 | # Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English |
| 86 | # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, | 114 | # (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, |
| 87 | # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), | 115 | # Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with |
| 88 | # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, | 116 | # English messages), Korean, Korean-en (Korean with English messages), Latvian, |
| 89 | # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, | 117 | # Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, |
| 90 | # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, | 118 | # Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, |
| 91 | # Ukrainian and Vietnamese. | 119 | # Swedish, Turkish, Ukrainian and Vietnamese. |
| 92 | # The default value is: English. | 120 | # The default value is: English. |
| 93 | 121 | ||
| 94 | OUTPUT_LANGUAGE = English | 122 | OUTPUT_LANGUAGE = English |
| @@ -209,6 +237,14 @@ QT_AUTOBRIEF = NO | |||
| 209 | 237 | ||
| 210 | MULTILINE_CPP_IS_BRIEF = NO | 238 | MULTILINE_CPP_IS_BRIEF = NO |
| 211 | 239 | ||
| 240 | # By default Python docstrings are displayed as preformatted text and doxygen's | ||
| 241 | # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the | ||
| 242 | # doxygen's special commands can be used and the contents of the docstring | ||
| 243 | # documentation blocks is shown as doxygen documentation. | ||
| 244 | # The default value is: YES. | ||
| 245 | |||
| 246 | PYTHON_DOCSTRING = YES | ||
| 247 | |||
| 212 | # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the | 248 | # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the |
| 213 | # documentation from any documented member that it re-implements. | 249 | # documentation from any documented member that it re-implements. |
| 214 | # The default value is: YES. | 250 | # The default value is: YES. |
| @@ -232,16 +268,16 @@ TAB_SIZE = 8 | |||
| 232 | # the documentation. An alias has the form: | 268 | # the documentation. An alias has the form: |
| 233 | # name=value | 269 | # name=value |
| 234 | # For example adding | 270 | # For example adding |
| 235 | # "sideeffect=@par Side Effects:\n" | 271 | # "sideeffect=@par Side Effects:^^" |
| 236 | # will allow you to put the command \sideeffect (or @sideeffect) in the | 272 | # will allow you to put the command \sideeffect (or @sideeffect) in the |
| 237 | # documentation, which will result in a user-defined paragraph with heading | 273 | # documentation, which will result in a user-defined paragraph with heading |
| 238 | # "Side Effects:". You can put \n's in the value part of an alias to insert | 274 | # "Side Effects:". Note that you cannot put \n's in the value part of an alias |
| 239 | # newlines (in the resulting output). You can put ^^ in the value part of an | 275 | # to insert newlines (in the resulting output). You can put ^^ in the value part |
| 240 | # alias to insert a newline as if a physical newline was in the original file. | 276 | # of an alias to insert a newline as if a physical newline was in the original |
| 241 | # When you need a literal { or } or , in the value part of an alias you have to | 277 | # file. When you need a literal { or } or , in the value part of an alias you |
| 242 | # escape them by means of a backslash (\), this can lead to conflicts with the | 278 | # have to escape them by means of a backslash (\), this can lead to conflicts |
| 243 | # commands \{ and \} for these it is advised to use the version @{ and @} or use | 279 | # with the commands \{ and \} for these it is advised to use the version @{ and |
| 244 | # a double escape (\\{ and \\}) | 280 | # @} or use a double escape (\\{ and \\}) |
| 245 | 281 | ||
| 246 | ALIASES = | 282 | ALIASES = |
| 247 | 283 | ||
| @@ -285,19 +321,22 @@ OPTIMIZE_OUTPUT_SLICE = YES | |||
| 285 | # parses. With this tag you can assign which parser to use for a given | 321 | # parses. With this tag you can assign which parser to use for a given |
| 286 | # extension. Doxygen has a built-in mapping, but you can override or extend it | 322 | # extension. Doxygen has a built-in mapping, but you can override or extend it |
| 287 | # using this tag. The format is ext=language, where ext is a file extension, and | 323 | # using this tag. The format is ext=language, where ext is a file extension, and |
| 288 | # language is one of the parsers supported by doxygen: IDL, Java, Javascript, | 324 | # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, |
| 289 | # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, | 325 | # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, |
| 290 | # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: | 326 | # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: |
| 291 | # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser | 327 | # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser |
| 292 | # tries to guess whether the code is fixed or free formatted code, this is the | 328 | # tries to guess whether the code is fixed or free formatted code, this is the |
| 293 | # default for Fortran type files), VHDL, tcl. For instance to make doxygen treat | 329 | # default for Fortran type files). For instance to make doxygen treat .inc files |
| 294 | # .inc files as Fortran files (default is PHP), and .f files as C (default is | 330 | # as Fortran files (default is PHP), and .f files as C (default is Fortran), |
| 295 | # Fortran), use: inc=Fortran f=C. | 331 | # use: inc=Fortran f=C. |
| 296 | # | 332 | # |
| 297 | # Note: For files without extension you can use no_extension as a placeholder. | 333 | # Note: For files without extension you can use no_extension as a placeholder. |
| 298 | # | 334 | # |
| 299 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise | 335 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise |
| 300 | # the files are not read by doxygen. | 336 | # the files are not read by doxygen. When specifying no_extension you should add |
| 337 | # * to the FILE_PATTERNS. | ||
| 338 | # | ||
| 339 | # Note see also the list of default file extension mappings. | ||
| 301 | 340 | ||
| 302 | EXTENSION_MAPPING = | 341 | EXTENSION_MAPPING = |
| 303 | 342 | ||
| @@ -315,11 +354,22 @@ MARKDOWN_SUPPORT = YES | |||
| 315 | # to that level are automatically included in the table of contents, even if | 354 | # to that level are automatically included in the table of contents, even if |
| 316 | # they do not have an id attribute. | 355 | # they do not have an id attribute. |
| 317 | # Note: This feature currently applies only to Markdown headings. | 356 | # Note: This feature currently applies only to Markdown headings. |
| 318 | # Minimum value: 0, maximum value: 99, default value: 5. | 357 | # Minimum value: 0, maximum value: 99, default value: 6. |
| 319 | # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. | 358 | # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. |
| 320 | 359 | ||
| 321 | TOC_INCLUDE_HEADINGS = 5 | 360 | TOC_INCLUDE_HEADINGS = 5 |
| 322 | 361 | ||
| 362 | # The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to | ||
| 363 | # generate identifiers for the Markdown headings. Note: Every identifier is | ||
| 364 | # unique. | ||
| 365 | # Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a | ||
| 366 | # sequence number starting at 0 and GITHUB use the lower case version of title | ||
| 367 | # with any whitespace replaced by '-' and punctuation characters removed. | ||
| 368 | # The default value is: DOXYGEN. | ||
| 369 | # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. | ||
| 370 | |||
| 371 | MARKDOWN_ID_STYLE = DOXYGEN | ||
| 372 | |||
| 323 | # When enabled doxygen tries to link words that correspond to documented | 373 | # When enabled doxygen tries to link words that correspond to documented |
| 324 | # classes, or namespaces to their corresponding documentation. Such a link can | 374 | # classes, or namespaces to their corresponding documentation. Such a link can |
| 325 | # be prevented in individual cases by putting a % sign in front of the word or | 375 | # be prevented in individual cases by putting a % sign in front of the word or |
| @@ -332,8 +382,8 @@ AUTOLINK_SUPPORT = YES | |||
| 332 | # to include (a tag file for) the STL sources as input, then you should set this | 382 | # to include (a tag file for) the STL sources as input, then you should set this |
| 333 | # tag to YES in order to let doxygen match functions declarations and | 383 | # tag to YES in order to let doxygen match functions declarations and |
| 334 | # definitions whose arguments contain STL classes (e.g. func(std::string); | 384 | # definitions whose arguments contain STL classes (e.g. func(std::string); |
| 335 | # versus func(std::string) {}). This also make the inheritance and collaboration | 385 | # versus func(std::string) {}). This also makes the inheritance and |
| 336 | # diagrams that involve STL classes more complete and accurate. | 386 | # collaboration diagrams that involve STL classes more complete and accurate. |
| 337 | # The default value is: NO. | 387 | # The default value is: NO. |
| 338 | 388 | ||
| 339 | BUILTIN_STL_SUPPORT = NO | 389 | BUILTIN_STL_SUPPORT = NO |
| @@ -345,9 +395,9 @@ BUILTIN_STL_SUPPORT = NO | |||
| 345 | CPP_CLI_SUPPORT = NO | 395 | CPP_CLI_SUPPORT = NO |
| 346 | 396 | ||
| 347 | # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: | 397 | # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: |
| 348 | # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen | 398 | # https://www.riverbankcomputing.com/software) sources only. Doxygen will parse |
| 349 | # will parse them like normal C++ but will assume all classes use public instead | 399 | # them like normal C++ but will assume all classes use public instead of private |
| 350 | # of private inheritance when no explicit protection keyword is present. | 400 | # inheritance when no explicit protection keyword is present. |
| 351 | # The default value is: NO. | 401 | # The default value is: NO. |
| 352 | 402 | ||
| 353 | SIP_SUPPORT = NO | 403 | SIP_SUPPORT = NO |
| @@ -431,6 +481,27 @@ TYPEDEF_HIDES_STRUCT = YES | |||
| 431 | 481 | ||
| 432 | LOOKUP_CACHE_SIZE = 0 | 482 | LOOKUP_CACHE_SIZE = 0 |
| 433 | 483 | ||
| 484 | # The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use | ||
| 485 | # during processing. When set to 0 doxygen will based this on the number of | ||
| 486 | # cores available in the system. You can set it explicitly to a value larger | ||
| 487 | # than 0 to get more control over the balance between CPU load and processing | ||
| 488 | # speed. At this moment only the input processing can be done using multiple | ||
| 489 | # threads. Since this is still an experimental feature the default is set to 1, | ||
| 490 | # which effectively disables parallel processing. Please report any issues you | ||
| 491 | # encounter. Generating dot graphs in parallel is controlled by the | ||
| 492 | # DOT_NUM_THREADS setting. | ||
| 493 | # Minimum value: 0, maximum value: 32, default value: 1. | ||
| 494 | |||
| 495 | NUM_PROC_THREADS = 1 | ||
| 496 | |||
| 497 | # If the TIMESTAMP tag is set different from NO then each generated page will | ||
| 498 | # contain the date or date and time when the page was generated. Setting this to | ||
| 499 | # NO can help when comparing the output of multiple runs. | ||
| 500 | # Possible values are: YES, NO, DATETIME and DATE. | ||
| 501 | # The default value is: NO. | ||
| 502 | |||
| 503 | TIMESTAMP = YES | ||
| 504 | |||
| 434 | #--------------------------------------------------------------------------- | 505 | #--------------------------------------------------------------------------- |
| 435 | # Build related configuration options | 506 | # Build related configuration options |
| 436 | #--------------------------------------------------------------------------- | 507 | #--------------------------------------------------------------------------- |
| @@ -494,6 +565,13 @@ EXTRACT_LOCAL_METHODS = NO | |||
| 494 | 565 | ||
| 495 | EXTRACT_ANON_NSPACES = NO | 566 | EXTRACT_ANON_NSPACES = NO |
| 496 | 567 | ||
| 568 | # If this flag is set to YES, the name of an unnamed parameter in a declaration | ||
| 569 | # will be determined by the corresponding definition. By default unnamed | ||
| 570 | # parameters remain unnamed in the output. | ||
| 571 | # The default value is: YES. | ||
| 572 | |||
| 573 | RESOLVE_UNNAMED_PARAMS = YES | ||
| 574 | |||
| 497 | # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all | 575 | # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all |
| 498 | # undocumented members inside documented classes or files. If set to NO these | 576 | # undocumented members inside documented classes or files. If set to NO these |
| 499 | # members will be included in the various overviews, but no documentation | 577 | # members will be included in the various overviews, but no documentation |
| @@ -505,14 +583,15 @@ HIDE_UNDOC_MEMBERS = NO | |||
| 505 | # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all | 583 | # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all |
| 506 | # undocumented classes that are normally visible in the class hierarchy. If set | 584 | # undocumented classes that are normally visible in the class hierarchy. If set |
| 507 | # to NO, these classes will be included in the various overviews. This option | 585 | # to NO, these classes will be included in the various overviews. This option |
| 508 | # has no effect if EXTRACT_ALL is enabled. | 586 | # will also hide undocumented C++ concepts if enabled. This option has no effect |
| 587 | # if EXTRACT_ALL is enabled. | ||
| 509 | # The default value is: NO. | 588 | # The default value is: NO. |
| 510 | 589 | ||
| 511 | HIDE_UNDOC_CLASSES = NO | 590 | HIDE_UNDOC_CLASSES = NO |
| 512 | 591 | ||
| 513 | # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend | 592 | # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend |
| 514 | # (class|struct|union) declarations. If set to NO, these declarations will be | 593 | # declarations. If set to NO, these declarations will be included in the |
| 515 | # included in the documentation. | 594 | # documentation. |
| 516 | # The default value is: NO. | 595 | # The default value is: NO. |
| 517 | 596 | ||
| 518 | HIDE_FRIEND_COMPOUNDS = NO | 597 | HIDE_FRIEND_COMPOUNDS = NO |
| @@ -531,12 +610,20 @@ HIDE_IN_BODY_DOCS = NO | |||
| 531 | 610 | ||
| 532 | INTERNAL_DOCS = NO | 611 | INTERNAL_DOCS = NO |
| 533 | 612 | ||
| 534 | # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file | 613 | # With the correct setting of option CASE_SENSE_NAMES doxygen will better be |
| 535 | # names in lower-case letters. If set to YES, upper-case letters are also | 614 | # able to match the capabilities of the underlying filesystem. In case the |
| 536 | # allowed. This is useful if you have classes or files whose names only differ | 615 | # filesystem is case sensitive (i.e. it supports files in the same directory |
| 537 | # in case and if your file system supports case sensitive file names. Windows | 616 | # whose names only differ in casing), the option must be set to YES to properly |
| 538 | # (including Cygwin) ands Mac users are advised to set this option to NO. | 617 | # deal with such files in case they appear in the input. For filesystems that |
| 539 | # The default value is: system dependent. | 618 | # are not case sensitive the option should be set to NO to properly deal with |
| 619 | # output files written for symbols that only differ in casing, such as for two | ||
| 620 | # classes, one named CLASS and the other named Class, and to also support | ||
| 621 | # references to files without having to specify the exact matching casing. On | ||
| 622 | # Windows (including Cygwin) and MacOS, users should typically set this option | ||
| 623 | # to NO, whereas on Linux or other Unix flavors it should typically be set to | ||
| 624 | # YES. | ||
| 625 | # Possible values are: SYSTEM, NO and YES. | ||
| 626 | # The default value is: SYSTEM. | ||
| 540 | 627 | ||
| 541 | CASE_SENSE_NAMES = NO | 628 | CASE_SENSE_NAMES = NO |
| 542 | 629 | ||
| @@ -554,6 +641,12 @@ HIDE_SCOPE_NAMES = NO | |||
| 554 | 641 | ||
| 555 | HIDE_COMPOUND_REFERENCE= NO | 642 | HIDE_COMPOUND_REFERENCE= NO |
| 556 | 643 | ||
| 644 | # If the SHOW_HEADERFILE tag is set to YES then the documentation for a class | ||
| 645 | # will show which file needs to be included to use the class. | ||
| 646 | # The default value is: YES. | ||
| 647 | |||
| 648 | SHOW_HEADERFILE = YES | ||
| 649 | |||
| 557 | # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of | 650 | # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of |
| 558 | # the files that are included by a file in the documentation of that file. | 651 | # the files that are included by a file in the documentation of that file. |
| 559 | # The default value is: YES. | 652 | # The default value is: YES. |
| @@ -711,7 +804,8 @@ FILE_VERSION_FILTER = | |||
| 711 | # output files in an output format independent way. To create the layout file | 804 | # output files in an output format independent way. To create the layout file |
| 712 | # that represents doxygen's defaults, run doxygen with the -l option. You can | 805 | # that represents doxygen's defaults, run doxygen with the -l option. You can |
| 713 | # optionally specify a file name after the option, if omitted DoxygenLayout.xml | 806 | # optionally specify a file name after the option, if omitted DoxygenLayout.xml |
| 714 | # will be used as the name of the layout file. | 807 | # will be used as the name of the layout file. See also section "Changing the |
| 808 | # layout of pages" for information. | ||
| 715 | # | 809 | # |
| 716 | # Note that if you run doxygen from a directory containing a file called | 810 | # Note that if you run doxygen from a directory containing a file called |
| 717 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE | 811 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE |
| @@ -757,24 +851,50 @@ WARNINGS = YES | |||
| 757 | WARN_IF_UNDOCUMENTED = YES | 851 | WARN_IF_UNDOCUMENTED = YES |
| 758 | 852 | ||
| 759 | # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for | 853 | # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for |
| 760 | # potential errors in the documentation, such as not documenting some parameters | 854 | # potential errors in the documentation, such as documenting some parameters in |
| 761 | # in a documented function, or documenting parameters that don't exist or using | 855 | # a documented function twice, or documenting parameters that don't exist or |
| 762 | # markup commands wrongly. | 856 | # using markup commands wrongly. |
| 763 | # The default value is: YES. | 857 | # The default value is: YES. |
| 764 | 858 | ||
| 765 | WARN_IF_DOC_ERROR = YES | 859 | WARN_IF_DOC_ERROR = YES |
| 766 | 860 | ||
| 861 | # If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete | ||
| 862 | # function parameter documentation. If set to NO, doxygen will accept that some | ||
| 863 | # parameters have no documentation without warning. | ||
| 864 | # The default value is: YES. | ||
| 865 | |||
| 866 | WARN_IF_INCOMPLETE_DOC = YES | ||
| 867 | |||
| 767 | # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that | 868 | # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that |
| 768 | # are documented, but have no documentation for their parameters or return | 869 | # are documented, but have no documentation for their parameters or return |
| 769 | # value. If set to NO, doxygen will only warn about wrong or incomplete | 870 | # value. If set to NO, doxygen will only warn about wrong parameter |
| 770 | # parameter documentation, but not about the absence of documentation. If | 871 | # documentation, but not about the absence of documentation. If EXTRACT_ALL is |
| 771 | # EXTRACT_ALL is set to YES then this flag will automatically be disabled. | 872 | # set to YES then this flag will automatically be disabled. See also |
| 873 | # WARN_IF_INCOMPLETE_DOC | ||
| 772 | # The default value is: NO. | 874 | # The default value is: NO. |
| 773 | 875 | ||
| 774 | WARN_NO_PARAMDOC = NO | 876 | WARN_NO_PARAMDOC = NO |
| 775 | 877 | ||
| 878 | # If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about | ||
| 879 | # undocumented enumeration values. If set to NO, doxygen will accept | ||
| 880 | # undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag | ||
| 881 | # will automatically be disabled. | ||
| 882 | # The default value is: NO. | ||
| 883 | |||
| 884 | WARN_IF_UNDOC_ENUM_VAL = NO | ||
| 885 | |||
| 776 | # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when | 886 | # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when |
| 777 | # a warning is encountered. | 887 | # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS |
| 888 | # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but | ||
| 889 | # at the end of the doxygen process doxygen will return with a non-zero status. | ||
| 890 | # If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves | ||
| 891 | # like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not | ||
| 892 | # write the warning messages in between other messages but write them at the end | ||
| 893 | # of a run, in case a WARN_LOGFILE is defined the warning messages will be | ||
| 894 | # besides being in the defined file also be shown at the end of a run, unless | ||
| 895 | # the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case | ||
| 896 | # the behavior will remain as with the setting FAIL_ON_WARNINGS. | ||
| 897 | # Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. | ||
| 778 | # The default value is: NO. | 898 | # The default value is: NO. |
| 779 | 899 | ||
| 780 | WARN_AS_ERROR = NO | 900 | WARN_AS_ERROR = NO |
| @@ -785,13 +905,27 @@ WARN_AS_ERROR = NO | |||
| 785 | # and the warning text. Optionally the format may contain $version, which will | 905 | # and the warning text. Optionally the format may contain $version, which will |
| 786 | # be replaced by the version of the file (if it could be obtained via | 906 | # be replaced by the version of the file (if it could be obtained via |
| 787 | # FILE_VERSION_FILTER) | 907 | # FILE_VERSION_FILTER) |
| 908 | # See also: WARN_LINE_FORMAT | ||
| 788 | # The default value is: $file:$line: $text. | 909 | # The default value is: $file:$line: $text. |
| 789 | 910 | ||
| 790 | WARN_FORMAT = "$file:$line: $text" | 911 | WARN_FORMAT = "$file:$line: $text" |
| 791 | 912 | ||
| 913 | # In the $text part of the WARN_FORMAT command it is possible that a reference | ||
| 914 | # to a more specific place is given. To make it easier to jump to this place | ||
| 915 | # (outside of doxygen) the user can define a custom "cut" / "paste" string. | ||
| 916 | # Example: | ||
| 917 | # WARN_LINE_FORMAT = "'vi $file +$line'" | ||
| 918 | # See also: WARN_FORMAT | ||
| 919 | # The default value is: at line $line of file $file. | ||
| 920 | |||
| 921 | WARN_LINE_FORMAT = "at line $line of file $file" | ||
| 922 | |||
| 792 | # The WARN_LOGFILE tag can be used to specify a file to which warning and error | 923 | # The WARN_LOGFILE tag can be used to specify a file to which warning and error |
| 793 | # messages should be written. If left blank the output is written to standard | 924 | # messages should be written. If left blank the output is written to standard |
| 794 | # error (stderr). | 925 | # error (stderr). In case the file specified cannot be opened for writing the |
| 926 | # warning and error messages are written to standard error. When as file - is | ||
| 927 | # specified the warning and error messages are written to standard output | ||
| 928 | # (stdout). | ||
| 795 | 929 | ||
| 796 | WARN_LOGFILE = | 930 | WARN_LOGFILE = |
| 797 | 931 | ||
| @@ -805,19 +939,29 @@ WARN_LOGFILE = | |||
| 805 | # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING | 939 | # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING |
| 806 | # Note: If this tag is empty the current directory is searched. | 940 | # Note: If this tag is empty the current directory is searched. |
| 807 | 941 | ||
| 808 | INPUT = \ | 942 | INPUT = include/@PACKAGE@ \ |
| 809 | include/@PACKAGE@ \ | 943 | README.md |
| 810 | README.md | ||
| 811 | 944 | ||
| 812 | # This tag can be used to specify the character encoding of the source files | 945 | # This tag can be used to specify the character encoding of the source files |
| 813 | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | 946 | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses |
| 814 | # libiconv (or the iconv built into libc) for the transcoding. See the libiconv | 947 | # libiconv (or the iconv built into libc) for the transcoding. See the libiconv |
| 815 | # documentation (see: https://www.gnu.org/software/libiconv/) for the list of | 948 | # documentation (see: |
| 816 | # possible encodings. | 949 | # https://www.gnu.org/software/libiconv/) for the list of possible encodings. |
| 950 | # See also: INPUT_FILE_ENCODING | ||
| 817 | # The default value is: UTF-8. | 951 | # The default value is: UTF-8. |
| 818 | 952 | ||
| 819 | INPUT_ENCODING = UTF-8 | 953 | INPUT_ENCODING = UTF-8 |
| 820 | 954 | ||
| 955 | # This tag can be used to specify the character encoding of the source files | ||
| 956 | # that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify | ||
| 957 | # character encoding on a per file pattern basis. Doxygen will compare the file | ||
| 958 | # name with each pattern and apply the encoding instead of the default | ||
| 959 | # INPUT_ENCODING) if there is a match. The character encodings are a list of the | ||
| 960 | # form: pattern=encoding (like *.php=ISO-8859-1). | ||
| 961 | # See also: INPUT_ENCODING for further information on supported encodings. | ||
| 962 | |||
| 963 | INPUT_FILE_ENCODING = | ||
| 964 | |||
| 821 | # If the value of the INPUT tag contains directories, you can use the | 965 | # If the value of the INPUT tag contains directories, you can use the |
| 822 | # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and | 966 | # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and |
| 823 | # *.h) to filter out the source-files in the directories. | 967 | # *.h) to filter out the source-files in the directories. |
| @@ -826,11 +970,15 @@ INPUT_ENCODING = UTF-8 | |||
| 826 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not | 970 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not |
| 827 | # read by doxygen. | 971 | # read by doxygen. |
| 828 | # | 972 | # |
| 829 | # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, | 973 | # Note the list of default checked file patterns might differ from the list of |
| 830 | # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, | 974 | # default file extension mappings. |
| 831 | # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, | 975 | # |
| 832 | # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, | 976 | # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, |
| 833 | # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. | 977 | # *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, |
| 978 | # *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, | ||
| 979 | # *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to | ||
| 980 | # be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, | ||
| 981 | # *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. | ||
| 834 | 982 | ||
| 835 | FILE_PATTERNS = | 983 | FILE_PATTERNS = |
| 836 | 984 | ||
| @@ -869,10 +1017,7 @@ EXCLUDE_PATTERNS = | |||
| 869 | # (namespaces, classes, functions, etc.) that should be excluded from the | 1017 | # (namespaces, classes, functions, etc.) that should be excluded from the |
| 870 | # output. The symbol name can be a fully qualified name, a word, or if the | 1018 | # output. The symbol name can be a fully qualified name, a word, or if the |
| 871 | # wildcard * is used, a substring. Examples: ANamespace, AClass, | 1019 | # wildcard * is used, a substring. Examples: ANamespace, AClass, |
| 872 | # AClass::ANamespace, ANamespace::*Test | 1020 | # ANamespace::AClass, ANamespace::*Test |
| 873 | # | ||
| 874 | # Note that the wildcards are matched against the file with absolute path, so to | ||
| 875 | # exclude all test directories use the pattern */test/* | ||
| 876 | 1021 | ||
| 877 | EXCLUDE_SYMBOLS = LIBIMOBILEDEVICE_API | 1022 | EXCLUDE_SYMBOLS = LIBIMOBILEDEVICE_API |
| 878 | 1023 | ||
| @@ -917,6 +1062,11 @@ IMAGE_PATH = | |||
| 917 | # code is scanned, but not when the output code is generated. If lines are added | 1062 | # code is scanned, but not when the output code is generated. If lines are added |
| 918 | # or removed, the anchors will not be placed correctly. | 1063 | # or removed, the anchors will not be placed correctly. |
| 919 | # | 1064 | # |
| 1065 | # Note that doxygen will use the data processed and written to standard output | ||
| 1066 | # for further processing, therefore nothing else, like debug statements or used | ||
| 1067 | # commands (so in case of a Windows batch file always use @echo OFF), should be | ||
| 1068 | # written to standard output. | ||
| 1069 | # | ||
| 920 | # Note that for custom extensions or not directly supported extensions you also | 1070 | # Note that for custom extensions or not directly supported extensions you also |
| 921 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not | 1071 | # need to set EXTENSION_MAPPING for the extension otherwise the files are not |
| 922 | # properly processed by doxygen. | 1072 | # properly processed by doxygen. |
| @@ -958,6 +1108,15 @@ FILTER_SOURCE_PATTERNS = | |||
| 958 | 1108 | ||
| 959 | USE_MDFILE_AS_MAINPAGE = README.md | 1109 | USE_MDFILE_AS_MAINPAGE = README.md |
| 960 | 1110 | ||
| 1111 | # The Fortran standard specifies that for fixed formatted Fortran code all | ||
| 1112 | # characters from position 72 are to be considered as comment. A common | ||
| 1113 | # extension is to allow longer lines before the automatic comment starts. The | ||
| 1114 | # setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can | ||
| 1115 | # be processed before the automatic comment starts. | ||
| 1116 | # Minimum value: 7, maximum value: 10000, default value: 72. | ||
| 1117 | |||
| 1118 | FORTRAN_COMMENT_AFTER = 72 | ||
| 1119 | |||
| 961 | #--------------------------------------------------------------------------- | 1120 | #--------------------------------------------------------------------------- |
| 962 | # Configuration options related to source browsing | 1121 | # Configuration options related to source browsing |
| 963 | #--------------------------------------------------------------------------- | 1122 | #--------------------------------------------------------------------------- |
| @@ -972,7 +1131,8 @@ USE_MDFILE_AS_MAINPAGE = README.md | |||
| 972 | SOURCE_BROWSER = NO | 1131 | SOURCE_BROWSER = NO |
| 973 | 1132 | ||
| 974 | # Setting the INLINE_SOURCES tag to YES will include the body of functions, | 1133 | # Setting the INLINE_SOURCES tag to YES will include the body of functions, |
| 975 | # classes and enums directly into the documentation. | 1134 | # multi-line macros, enums or list initialized variables directly into the |
| 1135 | # documentation. | ||
| 976 | # The default value is: NO. | 1136 | # The default value is: NO. |
| 977 | 1137 | ||
| 978 | INLINE_SOURCES = NO | 1138 | INLINE_SOURCES = NO |
| @@ -1055,10 +1215,11 @@ VERBATIM_HEADERS = NO | |||
| 1055 | 1215 | ||
| 1056 | ALPHABETICAL_INDEX = NO | 1216 | ALPHABETICAL_INDEX = NO |
| 1057 | 1217 | ||
| 1058 | # In case all classes in a project start with a common prefix, all classes will | 1218 | # The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) |
| 1059 | # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag | 1219 | # that should be ignored while generating the index headers. The IGNORE_PREFIX |
| 1060 | # can be used to specify a prefix (or a list of prefixes) that should be ignored | 1220 | # tag works for classes, function and member names. The entity will be placed in |
| 1061 | # while generating the index headers. | 1221 | # the alphabetical list under the first letter of the entity name that remains |
| 1222 | # after removing the prefix. | ||
| 1062 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. | 1223 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. |
| 1063 | 1224 | ||
| 1064 | IGNORE_PREFIX = | 1225 | IGNORE_PREFIX = |
| @@ -1137,11 +1298,15 @@ HTML_STYLESHEET = | |||
| 1137 | # Doxygen will copy the style sheet files to the output directory. | 1298 | # Doxygen will copy the style sheet files to the output directory. |
| 1138 | # Note: The order of the extra style sheet files is of importance (e.g. the last | 1299 | # Note: The order of the extra style sheet files is of importance (e.g. the last |
| 1139 | # style sheet in the list overrules the setting of the previous ones in the | 1300 | # style sheet in the list overrules the setting of the previous ones in the |
| 1140 | # list). For an example see the documentation. | 1301 | # list). |
| 1302 | # Note: Since the styling of scrollbars can currently not be overruled in | ||
| 1303 | # Webkit/Chromium, the styling will be left out of the default doxygen.css if | ||
| 1304 | # one or more extra stylesheets have been specified. So if scrollbar | ||
| 1305 | # customization is desired it has to be added explicitly. For an example see the | ||
| 1306 | # documentation. | ||
| 1141 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1307 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1142 | 1308 | ||
| 1143 | HTML_EXTRA_STYLESHEET = \ | 1309 | HTML_EXTRA_STYLESHEET = docs/doxygen/custom.css |
| 1144 | docs/doxygen/custom.css | ||
| 1145 | 1310 | ||
| 1146 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or | 1311 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or |
| 1147 | # other source files which should be copied to the HTML output directory. Note | 1312 | # other source files which should be copied to the HTML output directory. Note |
| @@ -1151,15 +1316,27 @@ HTML_EXTRA_STYLESHEET = \ | |||
| 1151 | # files will be copied as-is; there are no commands or markers available. | 1316 | # files will be copied as-is; there are no commands or markers available. |
| 1152 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1317 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1153 | 1318 | ||
| 1154 | HTML_EXTRA_FILES = \ | 1319 | HTML_EXTRA_FILES = docs/doxygen/favicon.ico \ |
| 1155 | docs/doxygen/favicon.ico \ | 1320 | docs/doxygen/folder.png \ |
| 1156 | docs/doxygen/folder.png \ | 1321 | docs/doxygen/folder-open.png \ |
| 1157 | docs/doxygen/folder-open.png \ | 1322 | docs/doxygen/text-x-generic.png |
| 1158 | docs/doxygen/text-x-generic.png | 1323 | |
| 1324 | # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output | ||
| 1325 | # should be rendered with a dark or light theme. | ||
| 1326 | # Possible values are: LIGHT always generates light mode output, DARK always | ||
| 1327 | # generates dark mode output, AUTO_LIGHT automatically sets the mode according | ||
| 1328 | # to the user preference, uses light mode if no preference is set (the default), | ||
| 1329 | # AUTO_DARK automatically sets the mode according to the user preference, uses | ||
| 1330 | # dark mode if no preference is set and TOGGLE allows a user to switch between | ||
| 1331 | # light and dark mode via a button. | ||
| 1332 | # The default value is: AUTO_LIGHT. | ||
| 1333 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1334 | |||
| 1335 | HTML_COLORSTYLE = AUTO_LIGHT | ||
| 1159 | 1336 | ||
| 1160 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen | 1337 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen |
| 1161 | # will adjust the colors in the style sheet and background images according to | 1338 | # will adjust the colors in the style sheet and background images according to |
| 1162 | # this color. Hue is specified as an angle on a colorwheel, see | 1339 | # this color. Hue is specified as an angle on a color-wheel, see |
| 1163 | # https://en.wikipedia.org/wiki/Hue for more information. For instance the value | 1340 | # https://en.wikipedia.org/wiki/Hue for more information. For instance the value |
| 1164 | # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 | 1341 | # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 |
| 1165 | # purple, and 360 is red again. | 1342 | # purple, and 360 is red again. |
| @@ -1169,7 +1346,7 @@ HTML_EXTRA_FILES = \ | |||
| 1169 | HTML_COLORSTYLE_HUE = 220 | 1346 | HTML_COLORSTYLE_HUE = 220 |
| 1170 | 1347 | ||
| 1171 | # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors | 1348 | # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors |
| 1172 | # in the HTML output. For a value of 0 the output will use grayscales only. A | 1349 | # in the HTML output. For a value of 0 the output will use gray-scales only. A |
| 1173 | # value of 255 will produce the most vivid colors. | 1350 | # value of 255 will produce the most vivid colors. |
| 1174 | # Minimum value: 0, maximum value: 255, default value: 100. | 1351 | # Minimum value: 0, maximum value: 255, default value: 100. |
| 1175 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1352 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| @@ -1187,20 +1364,11 @@ HTML_COLORSTYLE_SAT = 100 | |||
| 1187 | 1364 | ||
| 1188 | HTML_COLORSTYLE_GAMMA = 80 | 1365 | HTML_COLORSTYLE_GAMMA = 80 |
| 1189 | 1366 | ||
| 1190 | # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML | ||
| 1191 | # page will contain the date and time when the page was generated. Setting this | ||
| 1192 | # to YES can help to show when doxygen was last run and thus if the | ||
| 1193 | # documentation is up to date. | ||
| 1194 | # The default value is: NO. | ||
| 1195 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1196 | |||
| 1197 | HTML_TIMESTAMP = YES | ||
| 1198 | |||
| 1199 | # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML | 1367 | # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML |
| 1200 | # documentation will contain a main index with vertical navigation menus that | 1368 | # documentation will contain a main index with vertical navigation menus that |
| 1201 | # are dynamically created via Javascript. If disabled, the navigation index will | 1369 | # are dynamically created via JavaScript. If disabled, the navigation index will |
| 1202 | # consists of multiple levels of tabs that are statically embedded in every HTML | 1370 | # consists of multiple levels of tabs that are statically embedded in every HTML |
| 1203 | # page. Disable this option to support browsers that do not have Javascript, | 1371 | # page. Disable this option to support browsers that do not have JavaScript, |
| 1204 | # like the Qt help browser. | 1372 | # like the Qt help browser. |
| 1205 | # The default value is: YES. | 1373 | # The default value is: YES. |
| 1206 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1374 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| @@ -1215,6 +1383,33 @@ HTML_DYNAMIC_MENUS = NO | |||
| 1215 | 1383 | ||
| 1216 | HTML_DYNAMIC_SECTIONS = NO | 1384 | HTML_DYNAMIC_SECTIONS = NO |
| 1217 | 1385 | ||
| 1386 | # If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be | ||
| 1387 | # dynamically folded and expanded in the generated HTML source code. | ||
| 1388 | # The default value is: YES. | ||
| 1389 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1390 | |||
| 1391 | HTML_CODE_FOLDING = YES | ||
| 1392 | |||
| 1393 | # If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in | ||
| 1394 | # the top right corner of code and text fragments that allows the user to copy | ||
| 1395 | # its content to the clipboard. Note this only works if supported by the browser | ||
| 1396 | # and the web page is served via a secure context (see: | ||
| 1397 | # https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: | ||
| 1398 | # protocol. | ||
| 1399 | # The default value is: YES. | ||
| 1400 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1401 | |||
| 1402 | HTML_COPY_CLIPBOARD = YES | ||
| 1403 | |||
| 1404 | # Doxygen stores a couple of settings persistently in the browser (via e.g. | ||
| 1405 | # cookies). By default these settings apply to all HTML pages generated by | ||
| 1406 | # doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store | ||
| 1407 | # the settings under a project specific key, such that the user preferences will | ||
| 1408 | # be stored separately. | ||
| 1409 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1410 | |||
| 1411 | HTML_PROJECT_COOKIE = | ||
| 1412 | |||
| 1218 | # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries | 1413 | # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries |
| 1219 | # shown in the various tree structured indices initially; the user can expand | 1414 | # shown in the various tree structured indices initially; the user can expand |
| 1220 | # and collapse entries dynamically later on. Doxygen will expand the tree to | 1415 | # and collapse entries dynamically later on. Doxygen will expand the tree to |
| @@ -1230,10 +1425,11 @@ HTML_INDEX_NUM_ENTRIES = 100 | |||
| 1230 | 1425 | ||
| 1231 | # If the GENERATE_DOCSET tag is set to YES, additional index files will be | 1426 | # If the GENERATE_DOCSET tag is set to YES, additional index files will be |
| 1232 | # generated that can be used as input for Apple's Xcode 3 integrated development | 1427 | # generated that can be used as input for Apple's Xcode 3 integrated development |
| 1233 | # environment (see: https://developer.apple.com/xcode/), introduced with OSX | 1428 | # environment (see: |
| 1234 | # 10.5 (Leopard). To create a documentation set, doxygen will generate a | 1429 | # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To |
| 1235 | # Makefile in the HTML output directory. Running make will produce the docset in | 1430 | # create a documentation set, doxygen will generate a Makefile in the HTML |
| 1236 | # that directory and running make install will install the docset in | 1431 | # output directory. Running make will produce the docset in that directory and |
| 1432 | # running make install will install the docset in | ||
| 1237 | # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at | 1433 | # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at |
| 1238 | # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy | 1434 | # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy |
| 1239 | # genXcode/_index.html for more information. | 1435 | # genXcode/_index.html for more information. |
| @@ -1250,6 +1446,13 @@ GENERATE_DOCSET = NO | |||
| 1250 | 1446 | ||
| 1251 | DOCSET_FEEDNAME = "Doxygen generated docs" | 1447 | DOCSET_FEEDNAME = "Doxygen generated docs" |
| 1252 | 1448 | ||
| 1449 | # This tag determines the URL of the docset feed. A documentation feed provides | ||
| 1450 | # an umbrella under which multiple documentation sets from a single provider | ||
| 1451 | # (such as a company or product suite) can be grouped. | ||
| 1452 | # This tag requires that the tag GENERATE_DOCSET is set to YES. | ||
| 1453 | |||
| 1454 | DOCSET_FEEDURL = | ||
| 1455 | |||
| 1253 | # This tag specifies a string that should uniquely identify the documentation | 1456 | # This tag specifies a string that should uniquely identify the documentation |
| 1254 | # set bundle. This should be a reverse domain-name style string, e.g. | 1457 | # set bundle. This should be a reverse domain-name style string, e.g. |
| 1255 | # com.mycompany.MyDocSet. Doxygen will append .docset to the name. | 1458 | # com.mycompany.MyDocSet. Doxygen will append .docset to the name. |
| @@ -1275,8 +1478,12 @@ DOCSET_PUBLISHER_NAME = Publisher | |||
| 1275 | # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three | 1478 | # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three |
| 1276 | # additional HTML index files: index.hhp, index.hhc, and index.hhk. The | 1479 | # additional HTML index files: index.hhp, index.hhc, and index.hhk. The |
| 1277 | # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop | 1480 | # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop |
| 1278 | # (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on | 1481 | # on Windows. In the beginning of 2021 Microsoft took the original page, with |
| 1279 | # Windows. | 1482 | # a.o. the download links, offline the HTML help workshop was already many years |
| 1483 | # in maintenance mode). You can download the HTML help workshop from the web | ||
| 1484 | # archives at Installation executable (see: | ||
| 1485 | # http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo | ||
| 1486 | # ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). | ||
| 1280 | # | 1487 | # |
| 1281 | # The HTML Help Workshop contains a compiler that can convert all HTML output | 1488 | # The HTML Help Workshop contains a compiler that can convert all HTML output |
| 1282 | # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML | 1489 | # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML |
| @@ -1306,7 +1513,7 @@ CHM_FILE = | |||
| 1306 | HHC_LOCATION = | 1513 | HHC_LOCATION = |
| 1307 | 1514 | ||
| 1308 | # The GENERATE_CHI flag controls if a separate .chi index file is generated | 1515 | # The GENERATE_CHI flag controls if a separate .chi index file is generated |
| 1309 | # (YES) or that it should be included in the master .chm file (NO). | 1516 | # (YES) or that it should be included in the main .chm file (NO). |
| 1310 | # The default value is: NO. | 1517 | # The default value is: NO. |
| 1311 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | 1518 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. |
| 1312 | 1519 | ||
| @@ -1333,6 +1540,16 @@ BINARY_TOC = NO | |||
| 1333 | 1540 | ||
| 1334 | TOC_EXPAND = NO | 1541 | TOC_EXPAND = NO |
| 1335 | 1542 | ||
| 1543 | # The SITEMAP_URL tag is used to specify the full URL of the place where the | ||
| 1544 | # generated documentation will be placed on the server by the user during the | ||
| 1545 | # deployment of the documentation. The generated sitemap is called sitemap.xml | ||
| 1546 | # and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL | ||
| 1547 | # is specified no sitemap is generated. For information about the sitemap | ||
| 1548 | # protocol see https://www.sitemaps.org | ||
| 1549 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1550 | |||
| 1551 | SITEMAP_URL = | ||
| 1552 | |||
| 1336 | # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and | 1553 | # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and |
| 1337 | # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that | 1554 | # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that |
| 1338 | # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help | 1555 | # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help |
| @@ -1351,7 +1568,8 @@ QCH_FILE = | |||
| 1351 | 1568 | ||
| 1352 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help | 1569 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help |
| 1353 | # Project output. For more information please see Qt Help Project / Namespace | 1570 | # Project output. For more information please see Qt Help Project / Namespace |
| 1354 | # (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). | 1571 | # (see: |
| 1572 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). | ||
| 1355 | # The default value is: org.doxygen.Project. | 1573 | # The default value is: org.doxygen.Project. |
| 1356 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1574 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1357 | 1575 | ||
| @@ -1359,8 +1577,8 @@ QHP_NAMESPACE = org.doxygen.Project | |||
| 1359 | 1577 | ||
| 1360 | # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt | 1578 | # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt |
| 1361 | # Help Project output. For more information please see Qt Help Project / Virtual | 1579 | # Help Project output. For more information please see Qt Help Project / Virtual |
| 1362 | # Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- | 1580 | # Folders (see: |
| 1363 | # folders). | 1581 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). |
| 1364 | # The default value is: doc. | 1582 | # The default value is: doc. |
| 1365 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1583 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1366 | 1584 | ||
| @@ -1368,16 +1586,16 @@ QHP_VIRTUAL_FOLDER = doc | |||
| 1368 | 1586 | ||
| 1369 | # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom | 1587 | # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom |
| 1370 | # filter to add. For more information please see Qt Help Project / Custom | 1588 | # filter to add. For more information please see Qt Help Project / Custom |
| 1371 | # Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- | 1589 | # Filters (see: |
| 1372 | # filters). | 1590 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). |
| 1373 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1591 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1374 | 1592 | ||
| 1375 | QHP_CUST_FILTER_NAME = | 1593 | QHP_CUST_FILTER_NAME = |
| 1376 | 1594 | ||
| 1377 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the | 1595 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the |
| 1378 | # custom filter to add. For more information please see Qt Help Project / Custom | 1596 | # custom filter to add. For more information please see Qt Help Project / Custom |
| 1379 | # Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- | 1597 | # Filters (see: |
| 1380 | # filters). | 1598 | # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). |
| 1381 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1599 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1382 | 1600 | ||
| 1383 | QHP_CUST_FILTER_ATTRS = | 1601 | QHP_CUST_FILTER_ATTRS = |
| @@ -1389,9 +1607,9 @@ QHP_CUST_FILTER_ATTRS = | |||
| 1389 | 1607 | ||
| 1390 | QHP_SECT_FILTER_ATTRS = | 1608 | QHP_SECT_FILTER_ATTRS = |
| 1391 | 1609 | ||
| 1392 | # The QHG_LOCATION tag can be used to specify the location of Qt's | 1610 | # The QHG_LOCATION tag can be used to specify the location (absolute path |
| 1393 | # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the | 1611 | # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to |
| 1394 | # generated .qhp file. | 1612 | # run qhelpgenerator on the generated .qhp file. |
| 1395 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1613 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1396 | 1614 | ||
| 1397 | QHG_LOCATION = | 1615 | QHG_LOCATION = |
| @@ -1434,16 +1652,28 @@ DISABLE_INDEX = NO | |||
| 1434 | # to work a browser that supports JavaScript, DHTML, CSS and frames is required | 1652 | # to work a browser that supports JavaScript, DHTML, CSS and frames is required |
| 1435 | # (i.e. any modern browser). Windows users are probably better off using the | 1653 | # (i.e. any modern browser). Windows users are probably better off using the |
| 1436 | # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can | 1654 | # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can |
| 1437 | # further fine-tune the look of the index. As an example, the default style | 1655 | # further fine tune the look of the index (see "Fine-tuning the output"). As an |
| 1438 | # sheet generated by doxygen has an example that shows how to put an image at | 1656 | # example, the default style sheet generated by doxygen has an example that |
| 1439 | # the root of the tree instead of the PROJECT_NAME. Since the tree basically has | 1657 | # shows how to put an image at the root of the tree instead of the PROJECT_NAME. |
| 1440 | # the same information as the tab index, you could consider setting | 1658 | # Since the tree basically has the same information as the tab index, you could |
| 1441 | # DISABLE_INDEX to YES when enabling this option. | 1659 | # consider setting DISABLE_INDEX to YES when enabling this option. |
| 1442 | # The default value is: NO. | 1660 | # The default value is: NO. |
| 1443 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1661 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1444 | 1662 | ||
| 1445 | GENERATE_TREEVIEW = NONE | 1663 | GENERATE_TREEVIEW = NONE |
| 1446 | 1664 | ||
| 1665 | # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the | ||
| 1666 | # FULL_SIDEBAR option determines if the side bar is limited to only the treeview | ||
| 1667 | # area (value NO) or if it should extend to the full height of the window (value | ||
| 1668 | # YES). Setting this to YES gives a layout similar to | ||
| 1669 | # https://docs.readthedocs.io with more room for contents, but less room for the | ||
| 1670 | # project logo, title, and description. If either GENERATE_TREEVIEW or | ||
| 1671 | # DISABLE_INDEX is set to NO, this option has no effect. | ||
| 1672 | # The default value is: NO. | ||
| 1673 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1674 | |||
| 1675 | FULL_SIDEBAR = NO | ||
| 1676 | |||
| 1447 | # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that | 1677 | # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that |
| 1448 | # doxygen will group on one line in the generated HTML documentation. | 1678 | # doxygen will group on one line in the generated HTML documentation. |
| 1449 | # | 1679 | # |
| @@ -1468,6 +1698,24 @@ TREEVIEW_WIDTH = 250 | |||
| 1468 | 1698 | ||
| 1469 | EXT_LINKS_IN_WINDOW = NO | 1699 | EXT_LINKS_IN_WINDOW = NO |
| 1470 | 1700 | ||
| 1701 | # If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email | ||
| 1702 | # addresses. | ||
| 1703 | # The default value is: YES. | ||
| 1704 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1705 | |||
| 1706 | OBFUSCATE_EMAILS = YES | ||
| 1707 | |||
| 1708 | # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg | ||
| 1709 | # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see | ||
| 1710 | # https://inkscape.org) to generate formulas as SVG images instead of PNGs for | ||
| 1711 | # the HTML output. These images will generally look nicer at scaled resolutions. | ||
| 1712 | # Possible values are: png (the default) and svg (looks nicer but requires the | ||
| 1713 | # pdf2svg or inkscape tool). | ||
| 1714 | # The default value is: png. | ||
| 1715 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1716 | |||
| 1717 | HTML_FORMULA_FORMAT = png | ||
| 1718 | |||
| 1471 | # Use this tag to change the font size of LaTeX formulas included as images in | 1719 | # Use this tag to change the font size of LaTeX formulas included as images in |
| 1472 | # the HTML documentation. When you change the font size after a successful | 1720 | # the HTML documentation. When you change the font size after a successful |
| 1473 | # doxygen run you need to manually remove any form_*.png images from the HTML | 1721 | # doxygen run you need to manually remove any form_*.png images from the HTML |
| @@ -1477,19 +1725,14 @@ EXT_LINKS_IN_WINDOW = NO | |||
| 1477 | 1725 | ||
| 1478 | FORMULA_FONTSIZE = 10 | 1726 | FORMULA_FONTSIZE = 10 |
| 1479 | 1727 | ||
| 1480 | # Use the FORMULA_TRANSPARENT tag to determine whether or not the images | 1728 | # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands |
| 1481 | # generated for formulas are transparent PNGs. Transparent PNGs are not | 1729 | # to create new LaTeX commands to be used in formulas as building blocks. See |
| 1482 | # supported properly for IE 6.0, but are supported on all modern browsers. | 1730 | # the section "Including formulas" for details. |
| 1483 | # | ||
| 1484 | # Note that when changing this option you need to delete any form_*.png files in | ||
| 1485 | # the HTML output directory before the changes have effect. | ||
| 1486 | # The default value is: YES. | ||
| 1487 | # This tag requires that the tag GENERATE_HTML is set to YES. | ||
| 1488 | 1731 | ||
| 1489 | FORMULA_TRANSPARENT = YES | 1732 | FORMULA_MACROFILE = |
| 1490 | 1733 | ||
| 1491 | # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see | 1734 | # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see |
| 1492 | # https://www.mathjax.org) which uses client side Javascript for the rendering | 1735 | # https://www.mathjax.org) which uses client side JavaScript for the rendering |
| 1493 | # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX | 1736 | # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX |
| 1494 | # installed or if you want to formulas look prettier in the HTML output. When | 1737 | # installed or if you want to formulas look prettier in the HTML output. When |
| 1495 | # enabled you may also need to install MathJax separately and configure the path | 1738 | # enabled you may also need to install MathJax separately and configure the path |
| @@ -1499,11 +1742,29 @@ FORMULA_TRANSPARENT = YES | |||
| 1499 | 1742 | ||
| 1500 | USE_MATHJAX = NO | 1743 | USE_MATHJAX = NO |
| 1501 | 1744 | ||
| 1745 | # With MATHJAX_VERSION it is possible to specify the MathJax version to be used. | ||
| 1746 | # Note that the different versions of MathJax have different requirements with | ||
| 1747 | # regards to the different settings, so it is possible that also other MathJax | ||
| 1748 | # settings have to be changed when switching between the different MathJax | ||
| 1749 | # versions. | ||
| 1750 | # Possible values are: MathJax_2 and MathJax_3. | ||
| 1751 | # The default value is: MathJax_2. | ||
| 1752 | # This tag requires that the tag USE_MATHJAX is set to YES. | ||
| 1753 | |||
| 1754 | MATHJAX_VERSION = MathJax_2 | ||
| 1755 | |||
| 1502 | # When MathJax is enabled you can set the default output format to be used for | 1756 | # When MathJax is enabled you can set the default output format to be used for |
| 1503 | # the MathJax output. See the MathJax site (see: | 1757 | # the MathJax output. For more details about the output format see MathJax |
| 1504 | # http://docs.mathjax.org/en/latest/output.html) for more details. | 1758 | # version 2 (see: |
| 1759 | # http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 | ||
| 1760 | # (see: | ||
| 1761 | # http://docs.mathjax.org/en/latest/web/components/output.html). | ||
| 1505 | # Possible values are: HTML-CSS (which is slower, but has the best | 1762 | # Possible values are: HTML-CSS (which is slower, but has the best |
| 1506 | # compatibility), NativeMML (i.e. MathML) and SVG. | 1763 | # compatibility. This is the name for Mathjax version 2, for MathJax version 3 |
| 1764 | # this will be translated into chtml), NativeMML (i.e. MathML. Only supported | ||
| 1765 | # for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This | ||
| 1766 | # is the name for Mathjax version 3, for MathJax version 2 this will be | ||
| 1767 | # translated into HTML-CSS) and SVG. | ||
| 1507 | # The default value is: HTML-CSS. | 1768 | # The default value is: HTML-CSS. |
| 1508 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1769 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1509 | 1770 | ||
| @@ -1516,22 +1777,29 @@ MATHJAX_FORMAT = HTML-CSS | |||
| 1516 | # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax | 1777 | # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax |
| 1517 | # Content Delivery Network so you can quickly see the result without installing | 1778 | # Content Delivery Network so you can quickly see the result without installing |
| 1518 | # MathJax. However, it is strongly recommended to install a local copy of | 1779 | # MathJax. However, it is strongly recommended to install a local copy of |
| 1519 | # MathJax from https://www.mathjax.org before deployment. | 1780 | # MathJax from https://www.mathjax.org before deployment. The default value is: |
| 1520 | # The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. | 1781 | # - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 |
| 1782 | # - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 | ||
| 1521 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1783 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1522 | 1784 | ||
| 1523 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest | 1785 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest |
| 1524 | 1786 | ||
| 1525 | # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax | 1787 | # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax |
| 1526 | # extension names that should be enabled during MathJax rendering. For example | 1788 | # extension names that should be enabled during MathJax rendering. For example |
| 1789 | # for MathJax version 2 (see | ||
| 1790 | # https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): | ||
| 1527 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols | 1791 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols |
| 1792 | # For example for MathJax version 3 (see | ||
| 1793 | # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): | ||
| 1794 | # MATHJAX_EXTENSIONS = ams | ||
| 1528 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1795 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1529 | 1796 | ||
| 1530 | MATHJAX_EXTENSIONS = | 1797 | MATHJAX_EXTENSIONS = |
| 1531 | 1798 | ||
| 1532 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces | 1799 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces |
| 1533 | # of code that will be used on startup of the MathJax code. See the MathJax site | 1800 | # of code that will be used on startup of the MathJax code. See the MathJax site |
| 1534 | # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an | 1801 | # (see: |
| 1802 | # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an | ||
| 1535 | # example see the documentation. | 1803 | # example see the documentation. |
| 1536 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1804 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1537 | 1805 | ||
| @@ -1559,7 +1827,7 @@ MATHJAX_CODEFILE = | |||
| 1559 | SEARCHENGINE = NO | 1827 | SEARCHENGINE = NO |
| 1560 | 1828 | ||
| 1561 | # When the SERVER_BASED_SEARCH tag is enabled the search engine will be | 1829 | # When the SERVER_BASED_SEARCH tag is enabled the search engine will be |
| 1562 | # implemented using a web server instead of a web client using Javascript. There | 1830 | # implemented using a web server instead of a web client using JavaScript. There |
| 1563 | # are two flavors of web server based searching depending on the EXTERNAL_SEARCH | 1831 | # are two flavors of web server based searching depending on the EXTERNAL_SEARCH |
| 1564 | # setting. When disabled, doxygen will generate a PHP script for searching and | 1832 | # setting. When disabled, doxygen will generate a PHP script for searching and |
| 1565 | # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing | 1833 | # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing |
| @@ -1578,7 +1846,8 @@ SERVER_BASED_SEARCH = NO | |||
| 1578 | # | 1846 | # |
| 1579 | # Doxygen ships with an example indexer (doxyindexer) and search engine | 1847 | # Doxygen ships with an example indexer (doxyindexer) and search engine |
| 1580 | # (doxysearch.cgi) which are based on the open source search engine library | 1848 | # (doxysearch.cgi) which are based on the open source search engine library |
| 1581 | # Xapian (see: https://xapian.org/). | 1849 | # Xapian (see: |
| 1850 | # https://xapian.org/). | ||
| 1582 | # | 1851 | # |
| 1583 | # See the section "External Indexing and Searching" for details. | 1852 | # See the section "External Indexing and Searching" for details. |
| 1584 | # The default value is: NO. | 1853 | # The default value is: NO. |
| @@ -1591,8 +1860,9 @@ EXTERNAL_SEARCH = NO | |||
| 1591 | # | 1860 | # |
| 1592 | # Doxygen ships with an example indexer (doxyindexer) and search engine | 1861 | # Doxygen ships with an example indexer (doxyindexer) and search engine |
| 1593 | # (doxysearch.cgi) which are based on the open source search engine library | 1862 | # (doxysearch.cgi) which are based on the open source search engine library |
| 1594 | # Xapian (see: https://xapian.org/). See the section "External Indexing and | 1863 | # Xapian (see: |
| 1595 | # Searching" for details. | 1864 | # https://xapian.org/). See the section "External Indexing and Searching" for |
| 1865 | # details. | ||
| 1596 | # This tag requires that the tag SEARCHENGINE is set to YES. | 1866 | # This tag requires that the tag SEARCHENGINE is set to YES. |
| 1597 | 1867 | ||
| 1598 | SEARCHENGINE_URL = | 1868 | SEARCHENGINE_URL = |
| @@ -1701,29 +1971,31 @@ PAPER_TYPE = a4 | |||
| 1701 | 1971 | ||
| 1702 | EXTRA_PACKAGES = | 1972 | EXTRA_PACKAGES = |
| 1703 | 1973 | ||
| 1704 | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the | 1974 | # The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for |
| 1705 | # generated LaTeX document. The header should contain everything until the first | 1975 | # the generated LaTeX document. The header should contain everything until the |
| 1706 | # chapter. If it is left blank doxygen will generate a standard header. See | 1976 | # first chapter. If it is left blank doxygen will generate a standard header. It |
| 1707 | # section "Doxygen usage" for information on how to let doxygen write the | 1977 | # is highly recommended to start with a default header using |
| 1708 | # default header to a separate file. | 1978 | # doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty |
| 1979 | # and then modify the file new_header.tex. See also section "Doxygen usage" for | ||
| 1980 | # information on how to generate the default header that doxygen normally uses. | ||
| 1709 | # | 1981 | # |
| 1710 | # Note: Only use a user-defined header if you know what you are doing! The | 1982 | # Note: Only use a user-defined header if you know what you are doing! |
| 1711 | # following commands have a special meaning inside the header: $title, | 1983 | # Note: The header is subject to change so you typically have to regenerate the |
| 1712 | # $datetime, $date, $doxygenversion, $projectname, $projectnumber, | 1984 | # default header when upgrading to a newer version of doxygen. The following |
| 1713 | # $projectbrief, $projectlogo. Doxygen will replace $title with the empty | 1985 | # commands have a special meaning inside the header (and footer): For a |
| 1714 | # string, for the replacement values of the other commands the user is referred | 1986 | # description of the possible markers and block names see the documentation. |
| 1715 | # to HTML_HEADER. | ||
| 1716 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1987 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1717 | 1988 | ||
| 1718 | LATEX_HEADER = | 1989 | LATEX_HEADER = |
| 1719 | 1990 | ||
| 1720 | # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the | 1991 | # The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for |
| 1721 | # generated LaTeX document. The footer should contain everything after the last | 1992 | # the generated LaTeX document. The footer should contain everything after the |
| 1722 | # chapter. If it is left blank doxygen will generate a standard footer. See | 1993 | # last chapter. If it is left blank doxygen will generate a standard footer. See |
| 1723 | # LATEX_HEADER for more information on how to generate a default footer and what | 1994 | # LATEX_HEADER for more information on how to generate a default footer and what |
| 1724 | # special commands can be used inside the footer. | 1995 | # special commands can be used inside the footer. See also section "Doxygen |
| 1725 | # | 1996 | # usage" for information on how to generate the default footer that doxygen |
| 1726 | # Note: Only use a user-defined footer if you know what you are doing! | 1997 | # normally uses. Note: Only use a user-defined footer if you know what you are |
| 1998 | # doing! | ||
| 1727 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1999 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1728 | 2000 | ||
| 1729 | LATEX_FOOTER = | 2001 | LATEX_FOOTER = |
| @@ -1756,18 +2028,26 @@ LATEX_EXTRA_FILES = | |||
| 1756 | 2028 | ||
| 1757 | PDF_HYPERLINKS = NO | 2029 | PDF_HYPERLINKS = NO |
| 1758 | 2030 | ||
| 1759 | # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate | 2031 | # If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as |
| 1760 | # the PDF file directly from the LaTeX files. Set this option to YES, to get a | 2032 | # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX |
| 1761 | # higher quality PDF documentation. | 2033 | # files. Set this option to YES, to get a higher quality PDF documentation. |
| 2034 | # | ||
| 2035 | # See also section LATEX_CMD_NAME for selecting the engine. | ||
| 1762 | # The default value is: YES. | 2036 | # The default value is: YES. |
| 1763 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 2037 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1764 | 2038 | ||
| 1765 | USE_PDFLATEX = NO | 2039 | USE_PDFLATEX = NO |
| 1766 | 2040 | ||
| 1767 | # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode | 2041 | # The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. |
| 1768 | # command to the generated LaTeX files. This will instruct LaTeX to keep running | 2042 | # Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch |
| 1769 | # if errors occur, instead of asking the user for help. This option is also used | 2043 | # mode nothing is printed on the terminal, errors are scrolled as if <return> is |
| 1770 | # when generating formulas in HTML. | 2044 | # hit at every error; missing files that TeX tries to input or request from |
| 2045 | # keyboard input (\read on a not open input stream) cause the job to abort, | ||
| 2046 | # NON_STOP In nonstop mode the diagnostic message will appear on the terminal, | ||
| 2047 | # but there is no possibility of user interaction just like in batch mode, | ||
| 2048 | # SCROLL In scroll mode, TeX will stop only for missing files to input or if | ||
| 2049 | # keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at | ||
| 2050 | # each error, asking for user intervention. | ||
| 1771 | # The default value is: NO. | 2051 | # The default value is: NO. |
| 1772 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 2052 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1773 | 2053 | ||
| @@ -1788,14 +2068,6 @@ LATEX_HIDE_INDICES = NO | |||
| 1788 | 2068 | ||
| 1789 | LATEX_BIB_STYLE = plain | 2069 | LATEX_BIB_STYLE = plain |
| 1790 | 2070 | ||
| 1791 | # If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated | ||
| 1792 | # page will contain the date and time when the page was generated. Setting this | ||
| 1793 | # to NO can help when comparing the output of multiple runs. | ||
| 1794 | # The default value is: NO. | ||
| 1795 | # This tag requires that the tag GENERATE_LATEX is set to YES. | ||
| 1796 | |||
| 1797 | LATEX_TIMESTAMP = NO | ||
| 1798 | |||
| 1799 | # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) | 2071 | # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) |
| 1800 | # path from which the emoji images will be read. If a relative path is entered, | 2072 | # path from which the emoji images will be read. If a relative path is entered, |
| 1801 | # it will be relative to the LATEX_OUTPUT directory. If left blank the | 2073 | # it will be relative to the LATEX_OUTPUT directory. If left blank the |
| @@ -1860,6 +2132,14 @@ RTF_STYLESHEET_FILE = | |||
| 1860 | 2132 | ||
| 1861 | RTF_EXTENSIONS_FILE = | 2133 | RTF_EXTENSIONS_FILE = |
| 1862 | 2134 | ||
| 2135 | # The RTF_EXTRA_FILES tag can be used to specify one or more extra images or | ||
| 2136 | # other source files which should be copied to the RTF_OUTPUT output directory. | ||
| 2137 | # Note that the files will be copied as-is; there are no commands or markers | ||
| 2138 | # available. | ||
| 2139 | # This tag requires that the tag GENERATE_RTF is set to YES. | ||
| 2140 | |||
| 2141 | RTF_EXTRA_FILES = | ||
| 2142 | |||
| 1863 | #--------------------------------------------------------------------------- | 2143 | #--------------------------------------------------------------------------- |
| 1864 | # Configuration options related to the man page output | 2144 | # Configuration options related to the man page output |
| 1865 | #--------------------------------------------------------------------------- | 2145 | #--------------------------------------------------------------------------- |
| @@ -1961,7 +2241,7 @@ DOCBOOK_OUTPUT = docbook | |||
| 1961 | #--------------------------------------------------------------------------- | 2241 | #--------------------------------------------------------------------------- |
| 1962 | 2242 | ||
| 1963 | # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an | 2243 | # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an |
| 1964 | # AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures | 2244 | # AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures |
| 1965 | # the structure of the code including all documentation. Note that this feature | 2245 | # the structure of the code including all documentation. Note that this feature |
| 1966 | # is still experimental and incomplete at the moment. | 2246 | # is still experimental and incomplete at the moment. |
| 1967 | # The default value is: NO. | 2247 | # The default value is: NO. |
| @@ -1969,6 +2249,32 @@ DOCBOOK_OUTPUT = docbook | |||
| 1969 | GENERATE_AUTOGEN_DEF = NO | 2249 | GENERATE_AUTOGEN_DEF = NO |
| 1970 | 2250 | ||
| 1971 | #--------------------------------------------------------------------------- | 2251 | #--------------------------------------------------------------------------- |
| 2252 | # Configuration options related to Sqlite3 output | ||
| 2253 | #--------------------------------------------------------------------------- | ||
| 2254 | |||
| 2255 | # If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3 | ||
| 2256 | # database with symbols found by doxygen stored in tables. | ||
| 2257 | # The default value is: NO. | ||
| 2258 | |||
| 2259 | GENERATE_SQLITE3 = NO | ||
| 2260 | |||
| 2261 | # The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be | ||
| 2262 | # put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put | ||
| 2263 | # in front of it. | ||
| 2264 | # The default directory is: sqlite3. | ||
| 2265 | # This tag requires that the tag GENERATE_SQLITE3 is set to YES. | ||
| 2266 | |||
| 2267 | SQLITE3_OUTPUT = sqlite3 | ||
| 2268 | |||
| 2269 | # The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db | ||
| 2270 | # database file will be recreated with each doxygen run. If set to NO, doxygen | ||
| 2271 | # will warn if a database file is already found and not modify it. | ||
| 2272 | # The default value is: YES. | ||
| 2273 | # This tag requires that the tag GENERATE_SQLITE3 is set to YES. | ||
| 2274 | |||
| 2275 | SQLITE3_RECREATE_DB = YES | ||
| 2276 | |||
| 2277 | #--------------------------------------------------------------------------- | ||
| 1972 | # Configuration options related to the Perl module output | 2278 | # Configuration options related to the Perl module output |
| 1973 | #--------------------------------------------------------------------------- | 2279 | #--------------------------------------------------------------------------- |
| 1974 | 2280 | ||
| @@ -2042,7 +2348,8 @@ SEARCH_INCLUDES = NO | |||
| 2042 | 2348 | ||
| 2043 | # The INCLUDE_PATH tag can be used to specify one or more directories that | 2349 | # The INCLUDE_PATH tag can be used to specify one or more directories that |
| 2044 | # contain include files that are not input files but should be processed by the | 2350 | # contain include files that are not input files but should be processed by the |
| 2045 | # preprocessor. | 2351 | # preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of |
| 2352 | # RECURSIVE has no effect here. | ||
| 2046 | # This tag requires that the tag SEARCH_INCLUDES is set to YES. | 2353 | # This tag requires that the tag SEARCH_INCLUDES is set to YES. |
| 2047 | 2354 | ||
| 2048 | INCLUDE_PATH = | 2355 | INCLUDE_PATH = |
| @@ -2109,15 +2416,15 @@ TAGFILES = | |||
| 2109 | 2416 | ||
| 2110 | GENERATE_TAGFILE = | 2417 | GENERATE_TAGFILE = |
| 2111 | 2418 | ||
| 2112 | # If the ALLEXTERNALS tag is set to YES, all external class will be listed in | 2419 | # If the ALLEXTERNALS tag is set to YES, all external classes and namespaces |
| 2113 | # the class index. If set to NO, only the inherited external classes will be | 2420 | # will be listed in the class and namespace index. If set to NO, only the |
| 2114 | # listed. | 2421 | # inherited external classes will be listed. |
| 2115 | # The default value is: NO. | 2422 | # The default value is: NO. |
| 2116 | 2423 | ||
| 2117 | ALLEXTERNALS = NO | 2424 | ALLEXTERNALS = NO |
| 2118 | 2425 | ||
| 2119 | # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed | 2426 | # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed |
| 2120 | # in the modules index. If set to NO, only the current project's groups will be | 2427 | # in the topic index. If set to NO, only the current project's groups will be |
| 2121 | # listed. | 2428 | # listed. |
| 2122 | # The default value is: YES. | 2429 | # The default value is: YES. |
| 2123 | 2430 | ||
| @@ -2131,25 +2438,9 @@ EXTERNAL_GROUPS = YES | |||
| 2131 | EXTERNAL_PAGES = YES | 2438 | EXTERNAL_PAGES = YES |
| 2132 | 2439 | ||
| 2133 | #--------------------------------------------------------------------------- | 2440 | #--------------------------------------------------------------------------- |
| 2134 | # Configuration options related to the dot tool | 2441 | # Configuration options related to diagram generator tools |
| 2135 | #--------------------------------------------------------------------------- | 2442 | #--------------------------------------------------------------------------- |
| 2136 | 2443 | ||
| 2137 | # If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram | ||
| 2138 | # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to | ||
| 2139 | # NO turns the diagrams off. Note that this option also works with HAVE_DOT | ||
| 2140 | # disabled, but it is recommended to install and use dot, since it yields more | ||
| 2141 | # powerful graphs. | ||
| 2142 | # The default value is: YES. | ||
| 2143 | |||
| 2144 | CLASS_DIAGRAMS = YES | ||
| 2145 | |||
| 2146 | # You can include diagrams made with dia in doxygen documentation. Doxygen will | ||
| 2147 | # then run dia to produce the diagram and insert it in the documentation. The | ||
| 2148 | # DIA_PATH tag allows you to specify the directory where the dia binary resides. | ||
| 2149 | # If left empty dia is assumed to be found in the default search path. | ||
| 2150 | |||
| 2151 | DIA_PATH = | ||
| 2152 | |||
| 2153 | # If set to YES the inheritance and collaboration graphs will hide inheritance | 2444 | # If set to YES the inheritance and collaboration graphs will hide inheritance |
| 2154 | # and usage relations if the target is undocumented or is not a class. | 2445 | # and usage relations if the target is undocumented or is not a class. |
| 2155 | # The default value is: YES. | 2446 | # The default value is: YES. |
| @@ -2158,7 +2449,7 @@ HIDE_UNDOC_RELATIONS = YES | |||
| 2158 | 2449 | ||
| 2159 | # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is | 2450 | # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is |
| 2160 | # available from the path. This tool is part of Graphviz (see: | 2451 | # available from the path. This tool is part of Graphviz (see: |
| 2161 | # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent | 2452 | # https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent |
| 2162 | # Bell Labs. The other options in this section have no effect if this option is | 2453 | # Bell Labs. The other options in this section have no effect if this option is |
| 2163 | # set to NO | 2454 | # set to NO |
| 2164 | # The default value is: NO. | 2455 | # The default value is: NO. |
| @@ -2175,49 +2466,77 @@ HAVE_DOT = NO | |||
| 2175 | 2466 | ||
| 2176 | DOT_NUM_THREADS = 0 | 2467 | DOT_NUM_THREADS = 0 |
| 2177 | 2468 | ||
| 2178 | # When you want a differently looking font in the dot files that doxygen | 2469 | # DOT_COMMON_ATTR is common attributes for nodes, edges and labels of |
| 2179 | # generates you can specify the font name using DOT_FONTNAME. You need to make | 2470 | # subgraphs. When you want a differently looking font in the dot files that |
| 2180 | # sure dot is able to find the font, which can be done by putting it in a | 2471 | # doxygen generates you can specify fontname, fontcolor and fontsize attributes. |
| 2181 | # standard location or by setting the DOTFONTPATH environment variable or by | 2472 | # For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node, |
| 2182 | # setting DOT_FONTPATH to the directory containing the font. | 2473 | # Edge and Graph Attributes specification</a> You need to make sure dot is able |
| 2183 | # The default value is: Helvetica. | 2474 | # to find the font, which can be done by putting it in a standard location or by |
| 2475 | # setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the | ||
| 2476 | # directory containing the font. Default graphviz fontsize is 14. | ||
| 2477 | # The default value is: fontname=Helvetica,fontsize=10. | ||
| 2184 | # This tag requires that the tag HAVE_DOT is set to YES. | 2478 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2185 | 2479 | ||
| 2186 | DOT_FONTNAME = | 2480 | DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" |
| 2187 | 2481 | ||
| 2188 | # The DOT_FONTSIZE tag can be used to set the size (in points) of the font of | 2482 | # DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can |
| 2189 | # dot graphs. | 2483 | # add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a |
| 2190 | # Minimum value: 4, maximum value: 24, default value: 10. | 2484 | # href=https://graphviz.org/doc/info/arrows.html>Complete documentation about |
| 2485 | # arrows shapes.</a> | ||
| 2486 | # The default value is: labelfontname=Helvetica,labelfontsize=10. | ||
| 2191 | # This tag requires that the tag HAVE_DOT is set to YES. | 2487 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2192 | 2488 | ||
| 2193 | DOT_FONTSIZE = 10 | 2489 | DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" |
| 2194 | 2490 | ||
| 2195 | # By default doxygen will tell dot to use the default font as specified with | 2491 | # DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes |
| 2196 | # DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set | 2492 | # around nodes set 'shape=plain' or 'shape=plaintext' <a |
| 2197 | # the path where dot can find it using this tag. | 2493 | # href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a> |
| 2494 | # The default value is: shape=box,height=0.2,width=0.4. | ||
| 2495 | # This tag requires that the tag HAVE_DOT is set to YES. | ||
| 2496 | |||
| 2497 | DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" | ||
| 2498 | |||
| 2499 | # You can set the path where dot can find font specified with fontname in | ||
| 2500 | # DOT_COMMON_ATTR and others dot attributes. | ||
| 2198 | # This tag requires that the tag HAVE_DOT is set to YES. | 2501 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2199 | 2502 | ||
| 2200 | DOT_FONTPATH = | 2503 | DOT_FONTPATH = |
| 2201 | 2504 | ||
| 2202 | # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for | 2505 | # If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will |
| 2203 | # each documented class showing the direct and indirect inheritance relations. | 2506 | # generate a graph for each documented class showing the direct and indirect |
| 2204 | # Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. | 2507 | # inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and |
| 2508 | # HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case | ||
| 2509 | # the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the | ||
| 2510 | # CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. | ||
| 2511 | # If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance | ||
| 2512 | # relations will be shown as texts / links. Explicit enabling an inheritance | ||
| 2513 | # graph or choosing a different representation for an inheritance graph of a | ||
| 2514 | # specific class, can be accomplished by means of the command \inheritancegraph. | ||
| 2515 | # Disabling an inheritance graph can be accomplished by means of the command | ||
| 2516 | # \hideinheritancegraph. | ||
| 2517 | # Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. | ||
| 2205 | # The default value is: YES. | 2518 | # The default value is: YES. |
| 2206 | # This tag requires that the tag HAVE_DOT is set to YES. | ||
| 2207 | 2519 | ||
| 2208 | CLASS_GRAPH = YES | 2520 | CLASS_GRAPH = YES |
| 2209 | 2521 | ||
| 2210 | # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a | 2522 | # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a |
| 2211 | # graph for each documented class showing the direct and indirect implementation | 2523 | # graph for each documented class showing the direct and indirect implementation |
| 2212 | # dependencies (inheritance, containment, and class references variables) of the | 2524 | # dependencies (inheritance, containment, and class references variables) of the |
| 2213 | # class with other documented classes. | 2525 | # class with other documented classes. Explicit enabling a collaboration graph, |
| 2526 | # when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the | ||
| 2527 | # command \collaborationgraph. Disabling a collaboration graph can be | ||
| 2528 | # accomplished by means of the command \hidecollaborationgraph. | ||
| 2214 | # The default value is: YES. | 2529 | # The default value is: YES. |
| 2215 | # This tag requires that the tag HAVE_DOT is set to YES. | 2530 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2216 | 2531 | ||
| 2217 | COLLABORATION_GRAPH = YES | 2532 | COLLABORATION_GRAPH = YES |
| 2218 | 2533 | ||
| 2219 | # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for | 2534 | # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for |
| 2220 | # groups, showing the direct groups dependencies. | 2535 | # groups, showing the direct groups dependencies. Explicit enabling a group |
| 2536 | # dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means | ||
| 2537 | # of the command \groupgraph. Disabling a directory graph can be accomplished by | ||
| 2538 | # means of the command \hidegroupgraph. See also the chapter Grouping in the | ||
| 2539 | # manual. | ||
| 2221 | # The default value is: YES. | 2540 | # The default value is: YES. |
| 2222 | # This tag requires that the tag HAVE_DOT is set to YES. | 2541 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2223 | 2542 | ||
| @@ -2240,10 +2559,32 @@ UML_LOOK = NO | |||
| 2240 | # but if the number exceeds 15, the total amount of fields shown is limited to | 2559 | # but if the number exceeds 15, the total amount of fields shown is limited to |
| 2241 | # 10. | 2560 | # 10. |
| 2242 | # Minimum value: 0, maximum value: 100, default value: 10. | 2561 | # Minimum value: 0, maximum value: 100, default value: 10. |
| 2243 | # This tag requires that the tag HAVE_DOT is set to YES. | 2562 | # This tag requires that the tag UML_LOOK is set to YES. |
| 2244 | 2563 | ||
| 2245 | UML_LIMIT_NUM_FIELDS = 10 | 2564 | UML_LIMIT_NUM_FIELDS = 10 |
| 2246 | 2565 | ||
| 2566 | # If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and | ||
| 2567 | # methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS | ||
| 2568 | # tag is set to YES, doxygen will add type and arguments for attributes and | ||
| 2569 | # methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen | ||
| 2570 | # will not generate fields with class member information in the UML graphs. The | ||
| 2571 | # class diagrams will look similar to the default class diagrams but using UML | ||
| 2572 | # notation for the relationships. | ||
| 2573 | # Possible values are: NO, YES and NONE. | ||
| 2574 | # The default value is: NO. | ||
| 2575 | # This tag requires that the tag UML_LOOK is set to YES. | ||
| 2576 | |||
| 2577 | DOT_UML_DETAILS = NO | ||
| 2578 | |||
| 2579 | # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters | ||
| 2580 | # to display on a single line. If the actual line length exceeds this threshold | ||
| 2581 | # significantly it will be wrapped across multiple lines. Some heuristics are | ||
| 2582 | # applied to avoid ugly line breaks. | ||
| 2583 | # Minimum value: 0, maximum value: 1000, default value: 17. | ||
| 2584 | # This tag requires that the tag HAVE_DOT is set to YES. | ||
| 2585 | |||
| 2586 | DOT_WRAP_THRESHOLD = 17 | ||
| 2587 | |||
| 2247 | # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and | 2588 | # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and |
| 2248 | # collaboration graphs will show the relations between templates and their | 2589 | # collaboration graphs will show the relations between templates and their |
| 2249 | # instances. | 2590 | # instances. |
| @@ -2255,7 +2596,9 @@ TEMPLATE_RELATIONS = NO | |||
| 2255 | # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to | 2596 | # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to |
| 2256 | # YES then doxygen will generate a graph for each documented file showing the | 2597 | # YES then doxygen will generate a graph for each documented file showing the |
| 2257 | # direct and indirect include dependencies of the file with other documented | 2598 | # direct and indirect include dependencies of the file with other documented |
| 2258 | # files. | 2599 | # files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, |
| 2600 | # can be accomplished by means of the command \includegraph. Disabling an | ||
| 2601 | # include graph can be accomplished by means of the command \hideincludegraph. | ||
| 2259 | # The default value is: YES. | 2602 | # The default value is: YES. |
| 2260 | # This tag requires that the tag HAVE_DOT is set to YES. | 2603 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2261 | 2604 | ||
| @@ -2264,7 +2607,10 @@ INCLUDE_GRAPH = YES | |||
| 2264 | # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are | 2607 | # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are |
| 2265 | # set to YES then doxygen will generate a graph for each documented file showing | 2608 | # set to YES then doxygen will generate a graph for each documented file showing |
| 2266 | # the direct and indirect include dependencies of the file with other documented | 2609 | # the direct and indirect include dependencies of the file with other documented |
| 2267 | # files. | 2610 | # files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set |
| 2611 | # to NO, can be accomplished by means of the command \includedbygraph. Disabling | ||
| 2612 | # an included by graph can be accomplished by means of the command | ||
| 2613 | # \hideincludedbygraph. | ||
| 2268 | # The default value is: YES. | 2614 | # The default value is: YES. |
| 2269 | # This tag requires that the tag HAVE_DOT is set to YES. | 2615 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2270 | 2616 | ||
| @@ -2304,16 +2650,26 @@ GRAPHICAL_HIERARCHY = YES | |||
| 2304 | # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the | 2650 | # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the |
| 2305 | # dependencies a directory has on other directories in a graphical way. The | 2651 | # dependencies a directory has on other directories in a graphical way. The |
| 2306 | # dependency relations are determined by the #include relations between the | 2652 | # dependency relations are determined by the #include relations between the |
| 2307 | # files in the directories. | 2653 | # files in the directories. Explicit enabling a directory graph, when |
| 2654 | # DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command | ||
| 2655 | # \directorygraph. Disabling a directory graph can be accomplished by means of | ||
| 2656 | # the command \hidedirectorygraph. | ||
| 2308 | # The default value is: YES. | 2657 | # The default value is: YES. |
| 2309 | # This tag requires that the tag HAVE_DOT is set to YES. | 2658 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2310 | 2659 | ||
| 2311 | DIRECTORY_GRAPH = YES | 2660 | DIRECTORY_GRAPH = YES |
| 2312 | 2661 | ||
| 2662 | # The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels | ||
| 2663 | # of child directories generated in directory dependency graphs by dot. | ||
| 2664 | # Minimum value: 1, maximum value: 25, default value: 1. | ||
| 2665 | # This tag requires that the tag DIRECTORY_GRAPH is set to YES. | ||
| 2666 | |||
| 2667 | DIR_GRAPH_MAX_DEPTH = 1 | ||
| 2668 | |||
| 2313 | # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images | 2669 | # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images |
| 2314 | # generated by dot. For an explanation of the image formats see the section | 2670 | # generated by dot. For an explanation of the image formats see the section |
| 2315 | # output formats in the documentation of the dot tool (Graphviz (see: | 2671 | # output formats in the documentation of the dot tool (Graphviz (see: |
| 2316 | # http://www.graphviz.org/)). | 2672 | # https://www.graphviz.org/)). |
| 2317 | # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order | 2673 | # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order |
| 2318 | # to make the SVG files visible in IE 9+ (other browsers do not have this | 2674 | # to make the SVG files visible in IE 9+ (other browsers do not have this |
| 2319 | # requirement). | 2675 | # requirement). |
| @@ -2350,11 +2706,12 @@ DOT_PATH = | |||
| 2350 | 2706 | ||
| 2351 | DOTFILE_DIRS = | 2707 | DOTFILE_DIRS = |
| 2352 | 2708 | ||
| 2353 | # The MSCFILE_DIRS tag can be used to specify one or more directories that | 2709 | # You can include diagrams made with dia in doxygen documentation. Doxygen will |
| 2354 | # contain msc files that are included in the documentation (see the \mscfile | 2710 | # then run dia to produce the diagram and insert it in the documentation. The |
| 2355 | # command). | 2711 | # DIA_PATH tag allows you to specify the directory where the dia binary resides. |
| 2712 | # If left empty dia is assumed to be found in the default search path. | ||
| 2356 | 2713 | ||
| 2357 | MSCFILE_DIRS = | 2714 | DIA_PATH = |
| 2358 | 2715 | ||
| 2359 | # The DIAFILE_DIRS tag can be used to specify one or more directories that | 2716 | # The DIAFILE_DIRS tag can be used to specify one or more directories that |
| 2360 | # contain dia files that are included in the documentation (see the \diafile | 2717 | # contain dia files that are included in the documentation (see the \diafile |
| @@ -2363,10 +2720,10 @@ MSCFILE_DIRS = | |||
| 2363 | DIAFILE_DIRS = | 2720 | DIAFILE_DIRS = |
| 2364 | 2721 | ||
| 2365 | # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the | 2722 | # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the |
| 2366 | # path where java can find the plantuml.jar file. If left blank, it is assumed | 2723 | # path where java can find the plantuml.jar file or to the filename of jar file |
| 2367 | # PlantUML is not used or called during a preprocessing step. Doxygen will | 2724 | # to be used. If left blank, it is assumed PlantUML is not used or called during |
| 2368 | # generate a warning when it encounters a \startuml command in this case and | 2725 | # a preprocessing step. Doxygen will generate a warning when it encounters a |
| 2369 | # will not generate output for the diagram. | 2726 | # \startuml command in this case and will not generate output for the diagram. |
| 2370 | 2727 | ||
| 2371 | PLANTUML_JAR_PATH = | 2728 | PLANTUML_JAR_PATH = |
| 2372 | 2729 | ||
| @@ -2383,7 +2740,7 @@ PLANTUML_INCLUDE_PATH = | |||
| 2383 | # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes | 2740 | # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes |
| 2384 | # that will be shown in the graph. If the number of nodes in a graph becomes | 2741 | # that will be shown in the graph. If the number of nodes in a graph becomes |
| 2385 | # larger than this value, doxygen will truncate the graph, which is visualized | 2742 | # larger than this value, doxygen will truncate the graph, which is visualized |
| 2386 | # by representing a node as a red box. Note that doxygen if the number of direct | 2743 | # by representing a node as a red box. Note that if the number of direct |
| 2387 | # children of the root node in a graph is already larger than | 2744 | # children of the root node in a graph is already larger than |
| 2388 | # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that | 2745 | # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that |
| 2389 | # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. | 2746 | # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. |
| @@ -2404,18 +2761,6 @@ DOT_GRAPH_MAX_NODES = 50 | |||
| 2404 | 2761 | ||
| 2405 | MAX_DOT_GRAPH_DEPTH = 0 | 2762 | MAX_DOT_GRAPH_DEPTH = 0 |
| 2406 | 2763 | ||
| 2407 | # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent | ||
| 2408 | # background. This is disabled by default, because dot on Windows does not seem | ||
| 2409 | # to support this out of the box. | ||
| 2410 | # | ||
| 2411 | # Warning: Depending on the platform used, enabling this option may lead to | ||
| 2412 | # badly anti-aliased labels on the edges of a graph (i.e. they become hard to | ||
| 2413 | # read). | ||
| 2414 | # The default value is: NO. | ||
| 2415 | # This tag requires that the tag HAVE_DOT is set to YES. | ||
| 2416 | |||
| 2417 | DOT_TRANSPARENT = NO | ||
| 2418 | |||
| 2419 | # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output | 2764 | # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output |
| 2420 | # files in one run (i.e. multiple -o and -T options on the command line). This | 2765 | # files in one run (i.e. multiple -o and -T options on the command line). This |
| 2421 | # makes dot run faster, but since only newer versions of dot (>1.8.10) support | 2766 | # makes dot run faster, but since only newer versions of dot (>1.8.10) support |
| @@ -2428,14 +2773,34 @@ DOT_MULTI_TARGETS = NO | |||
| 2428 | # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page | 2773 | # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page |
| 2429 | # explaining the meaning of the various boxes and arrows in the dot generated | 2774 | # explaining the meaning of the various boxes and arrows in the dot generated |
| 2430 | # graphs. | 2775 | # graphs. |
| 2776 | # Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal | ||
| 2777 | # graphical representation for inheritance and collaboration diagrams is used. | ||
| 2431 | # The default value is: YES. | 2778 | # The default value is: YES. |
| 2432 | # This tag requires that the tag HAVE_DOT is set to YES. | 2779 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2433 | 2780 | ||
| 2434 | GENERATE_LEGEND = YES | 2781 | GENERATE_LEGEND = YES |
| 2435 | 2782 | ||
| 2436 | # If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot | 2783 | # If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate |
| 2437 | # files that are used to generate the various graphs. | 2784 | # files that are used to generate the various graphs. |
| 2785 | # | ||
| 2786 | # Note: This setting is not only used for dot files but also for msc temporary | ||
| 2787 | # files. | ||
| 2438 | # The default value is: YES. | 2788 | # The default value is: YES. |
| 2439 | # This tag requires that the tag HAVE_DOT is set to YES. | ||
| 2440 | 2789 | ||
| 2441 | DOT_CLEANUP = YES | 2790 | DOT_CLEANUP = YES |
| 2791 | |||
| 2792 | # You can define message sequence charts within doxygen comments using the \msc | ||
| 2793 | # command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will | ||
| 2794 | # use a built-in version of mscgen tool to produce the charts. Alternatively, | ||
| 2795 | # the MSCGEN_TOOL tag can also specify the name an external tool. For instance, | ||
| 2796 | # specifying prog as the value, doxygen will call the tool as prog -T | ||
| 2797 | # <outfile_format> -o <outputfile> <inputfile>. The external tool should support | ||
| 2798 | # output file formats "png", "eps", "svg", and "ismap". | ||
| 2799 | |||
| 2800 | MSCGEN_TOOL = | ||
| 2801 | |||
| 2802 | # The MSCFILE_DIRS tag can be used to specify one or more directories that | ||
| 2803 | # contain msc files that are included in the documentation (see the \mscfile | ||
| 2804 | # command). | ||
| 2805 | |||
| 2806 | MSCFILE_DIRS = | ||
diff --git a/include/Makefile.am b/include/Makefile.am index 2abaf49..a41f53d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am | |||
| @@ -23,9 +23,11 @@ nobase_include_HEADERS = \ | |||
| 23 | libimobiledevice/diagnostics_relay.h \ | 23 | libimobiledevice/diagnostics_relay.h \ |
| 24 | libimobiledevice/debugserver.h \ | 24 | libimobiledevice/debugserver.h \ |
| 25 | libimobiledevice/syslog_relay.h \ | 25 | libimobiledevice/syslog_relay.h \ |
| 26 | libimobiledevice/ostrace.h \ | ||
| 26 | libimobiledevice/mobileactivation.h \ | 27 | libimobiledevice/mobileactivation.h \ |
| 27 | libimobiledevice/preboard.h \ | 28 | libimobiledevice/preboard.h \ |
| 28 | libimobiledevice/companion_proxy.h \ | 29 | libimobiledevice/companion_proxy.h \ |
| 29 | libimobiledevice/reverse_proxy.h \ | 30 | libimobiledevice/reverse_proxy.h \ |
| 31 | libimobiledevice/bt_packet_logger.h \ | ||
| 30 | libimobiledevice/property_list_service.h \ | 32 | libimobiledevice/property_list_service.h \ |
| 31 | libimobiledevice/service.h | 33 | libimobiledevice/service.h |
diff --git a/include/endianness.h b/include/endianness.h index 88b63db..972e51b 100644 --- a/include/endianness.h +++ b/include/endianness.h | |||
| @@ -19,6 +19,13 @@ | |||
| 19 | #endif | 19 | #endif |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | #ifndef __BYTE_ORDER | ||
| 23 | #ifndef _WIN32 | ||
| 24 | #warning __BYTE_ORDER is not defined, assuming little endian | ||
| 25 | #endif | ||
| 26 | #define __BYTE_ORDER __LITTLE_ENDIAN | ||
| 27 | #endif | ||
| 28 | |||
| 22 | #ifndef be16toh | 29 | #ifndef be16toh |
| 23 | #if __BYTE_ORDER == __BIG_ENDIAN | 30 | #if __BYTE_ORDER == __BIG_ENDIAN |
| 24 | #define be16toh(x) (x) | 31 | #define be16toh(x) (x) |
diff --git a/include/libimobiledevice/afc.h b/include/libimobiledevice/afc.h index 4ad3dbd..6e404c3 100644 --- a/include/libimobiledevice/afc.h +++ b/include/libimobiledevice/afc.h | |||
| @@ -64,6 +64,7 @@ typedef enum { | |||
| 64 | AFC_E_NO_MEM = 31, | 64 | AFC_E_NO_MEM = 31, |
| 65 | AFC_E_NOT_ENOUGH_DATA = 32, | 65 | AFC_E_NOT_ENOUGH_DATA = 32, |
| 66 | AFC_E_DIR_NOT_EMPTY = 33, | 66 | AFC_E_DIR_NOT_EMPTY = 33, |
| 67 | AFC_E_SSL_ERROR = 34, | ||
| 67 | AFC_E_FORCE_SIGNED_TYPE = -1 | 68 | AFC_E_FORCE_SIGNED_TYPE = -1 |
| 68 | } afc_error_t; | 69 | } afc_error_t; |
| 69 | 70 | ||
| @@ -145,6 +146,20 @@ LIBIMOBILEDEVICE_API afc_error_t afc_client_free(afc_client_t client); | |||
| 145 | LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info(afc_client_t client, char ***device_information); | 146 | LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info(afc_client_t client, char ***device_information); |
| 146 | 147 | ||
| 147 | /** | 148 | /** |
| 149 | * Get device information for a connected client. The device information | ||
| 150 | * returned is the device model as well as the free space, the total capacity | ||
| 151 | * and blocksize on the accessed disk partition. | ||
| 152 | * | ||
| 153 | * @param client The client to get device info for. | ||
| 154 | * @param device_information A pointer to a plist_t that will be populated | ||
| 155 | * with key-value pairs (dictionary) representing the device’s | ||
| 156 | * storage and model information. Free with plist_free(). | ||
| 157 | * | ||
| 158 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value. | ||
| 159 | */ | ||
| 160 | LIBIMOBILEDEVICE_API afc_error_t afc_get_device_info_plist(afc_client_t client, plist_t *device_information); | ||
| 161 | |||
| 162 | /** | ||
| 148 | * Gets a directory listing of the directory requested. | 163 | * Gets a directory listing of the directory requested. |
| 149 | * | 164 | * |
| 150 | * @param client The client to get a directory listing from. | 165 | * @param client The client to get a directory listing from. |
| @@ -163,7 +178,7 @@ LIBIMOBILEDEVICE_API afc_error_t afc_read_directory(afc_client_t client, const c | |||
| 163 | * @param client The client to use to get the information of the file. | 178 | * @param client The client to use to get the information of the file. |
| 164 | * @param path The fully-qualified path to the file. | 179 | * @param path The fully-qualified path to the file. |
| 165 | * @param file_information Pointer to a buffer that will be filled with a | 180 | * @param file_information Pointer to a buffer that will be filled with a |
| 166 | * NULL-terminated list of strings with the file information. Set to NULL | 181 | * NULL-terminated list of strings with the file attributes. Set to NULL |
| 167 | * before calling this function. Free with afc_dictionary_free(). | 182 | * before calling this function. Free with afc_dictionary_free(). |
| 168 | * | 183 | * |
| 169 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value. | 184 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value. |
| @@ -171,6 +186,19 @@ LIBIMOBILEDEVICE_API afc_error_t afc_read_directory(afc_client_t client, const c | |||
| 171 | LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***file_information); | 186 | LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***file_information); |
| 172 | 187 | ||
| 173 | /** | 188 | /** |
| 189 | * Gets information about a specific file. | ||
| 190 | * | ||
| 191 | * @param client The client to use to get the information of the file. | ||
| 192 | * @param path The fully-qualified path to the file. | ||
| 193 | * @param file_information A pointer to a plist_t that will be populated | ||
| 194 | * with key-value pairs (dictionary) representing the file attributes. | ||
| 195 | * Free with plist_free(). | ||
| 196 | * | ||
| 197 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value. | ||
| 198 | */ | ||
| 199 | LIBIMOBILEDEVICE_API afc_error_t afc_get_file_info_plist(afc_client_t client, const char *path, plist_t *file_information); | ||
| 200 | |||
| 201 | /** | ||
| 174 | * Opens a file on the device. | 202 | * Opens a file on the device. |
| 175 | * | 203 | * |
| 176 | * @param client The client to use to open the file. | 204 | * @param client The client to use to open the file. |
diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h index a9d270b..bc57778 100644 --- a/include/libimobiledevice/libimobiledevice.h +++ b/include/libimobiledevice/libimobiledevice.h | |||
| @@ -31,10 +31,13 @@ extern "C" { | |||
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #include <stdint.h> | 33 | #include <stdint.h> |
| 34 | #include <sys/types.h> | ||
| 35 | #include <sys/stat.h> | ||
| 36 | #include <plist/plist.h> | 34 | #include <plist/plist.h> |
| 37 | 35 | ||
| 36 | #if defined(_MSC_VER) | ||
| 37 | #include <basetsd.h> | ||
| 38 | typedef SSIZE_T ssize_t; | ||
| 39 | #endif | ||
| 40 | |||
| 38 | #ifndef LIBIMOBILEDEVICE_API | 41 | #ifndef LIBIMOBILEDEVICE_API |
| 39 | #ifdef LIBIMOBILEDEVICE_STATIC | 42 | #ifdef LIBIMOBILEDEVICE_STATIC |
| 40 | #define LIBIMOBILEDEVICE_API | 43 | #define LIBIMOBILEDEVICE_API |
| @@ -401,12 +404,38 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_handle(idevice_t device, uint32 | |||
| 401 | LIBIMOBILEDEVICE_API idevice_error_t idevice_get_udid(idevice_t device, char **udid); | 404 | LIBIMOBILEDEVICE_API idevice_error_t idevice_get_udid(idevice_t device, char **udid); |
| 402 | 405 | ||
| 403 | /** | 406 | /** |
| 407 | * Returns the device ProductVersion in numerical form, where "X.Y.Z" | ||
| 408 | * will be returned as (X << 16) | (Y << 8) | Z . | ||
| 409 | * Use IDEVICE_DEVICE_VERSION macro for easy version comparison. | ||
| 410 | * @see IDEVICE_DEVICE_VERSION | ||
| 411 | * | ||
| 412 | * @param client Initialized device client | ||
| 413 | * | ||
| 414 | * @return A numerical representation of the X.Y.Z ProductVersion string | ||
| 415 | * or 0 if the version cannot be retrieved. | ||
| 416 | */ | ||
| 417 | LIBIMOBILEDEVICE_API unsigned int idevice_get_device_version(idevice_t device); | ||
| 418 | |||
| 419 | /** | ||
| 420 | * Gets a readable error string for a given idevice error code. | ||
| 421 | * | ||
| 422 | * @param err An idevice error code | ||
| 423 | * | ||
| 424 | * @return A readable error string | ||
| 425 | */ | ||
| 426 | LIBIMOBILEDEVICE_API const char* idevice_strerror(idevice_error_t err); | ||
| 427 | |||
| 428 | /** | ||
| 404 | * Returns a static string of the libimobiledevice version. | 429 | * Returns a static string of the libimobiledevice version. |
| 405 | * | 430 | * |
| 406 | * @return The libimobiledevice version as static ascii string | 431 | * @return The libimobiledevice version as static ascii string |
| 407 | */ | 432 | */ |
| 408 | LIBIMOBILEDEVICE_API const char* libimobiledevice_version(); | 433 | LIBIMOBILEDEVICE_API const char* libimobiledevice_version(); |
| 409 | 434 | ||
| 435 | /* macros */ | ||
| 436 | /** Helper macro to get a numerical representation of a product version tuple */ | ||
| 437 | #define IDEVICE_DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF)) | ||
| 438 | |||
| 410 | #ifdef __cplusplus | 439 | #ifdef __cplusplus |
| 411 | } | 440 | } |
| 412 | #endif | 441 | #endif |
diff --git a/include/libimobiledevice/ostrace.h b/include/libimobiledevice/ostrace.h new file mode 100644 index 0000000..f083ba7 --- /dev/null +++ b/include/libimobiledevice/ostrace.h | |||
| @@ -0,0 +1,198 @@ | |||
| 1 | /** | ||
| 2 | * @file libimobiledevice/ostrace.h | ||
| 3 | * @brief System log and tracing capabilities. | ||
| 4 | * \internal | ||
| 5 | * | ||
| 6 | * Copyright (c) 2020-2025 Nikias Bassen, All Rights Reserved. | ||
| 7 | * | ||
| 8 | * This library is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU Lesser General Public | ||
| 10 | * License as published by the Free Software Foundation; either | ||
| 11 | * version 2.1 of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This library is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * Lesser General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU Lesser General Public | ||
| 19 | * License along with this library; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef OSTRACE_H | ||
| 24 | #define OSTRACE_H | ||
| 25 | |||
| 26 | #ifdef __cplusplus | ||
| 27 | extern "C" { | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #include <libimobiledevice/libimobiledevice.h> | ||
| 31 | #include <libimobiledevice/lockdown.h> | ||
| 32 | |||
| 33 | /** Service identifier passed to lockdownd_start_service() to start the os trace relay service */ | ||
| 34 | #define OSTRACE_SERVICE_NAME "com.apple.os_trace_relay" | ||
| 35 | |||
| 36 | /** Error Codes */ | ||
| 37 | typedef enum { | ||
| 38 | OSTRACE_E_SUCCESS = 0, | ||
| 39 | OSTRACE_E_INVALID_ARG = -1, | ||
| 40 | OSTRACE_E_MUX_ERROR = -2, | ||
| 41 | OSTRACE_E_SSL_ERROR = -3, | ||
| 42 | OSTRACE_E_NOT_ENOUGH_DATA = -4, | ||
| 43 | OSTRACE_E_TIMEOUT = -5, | ||
| 44 | OSTRACE_E_PLIST_ERROR = -6, | ||
| 45 | OSTRACE_E_REQUEST_FAILED = -7, | ||
| 46 | OSTRACE_E_UNKNOWN_ERROR = -256 | ||
| 47 | } ostrace_error_t; | ||
| 48 | |||
| 49 | typedef struct ostrace_client_private ostrace_client_private; /**< \private */ | ||
| 50 | typedef ostrace_client_private *ostrace_client_t; /**< The client handle. */ | ||
| 51 | |||
| 52 | #pragma pack(push,1) | ||
| 53 | struct ostrace_packet_header_t { | ||
| 54 | uint8_t marker; | ||
| 55 | uint32_t type; | ||
| 56 | uint32_t header_size; // 0x81 | ||
| 57 | uint32_t pid; | ||
| 58 | uint64_t procid; // == pid | ||
| 59 | unsigned char procuuid[16]; // procuuid | ||
| 60 | uint16_t procpath_len; // path to process | ||
| 61 | uint64_t aid; // activity id, usually 0 | ||
| 62 | uint64_t paid; // (parent?) activity id, usually 0 | ||
| 63 | uint64_t time_sec; // tv.tv_sec 64 bit | ||
| 64 | uint32_t time_usec; // tv.usec 32 bit | ||
| 65 | uint8_t unk06; | ||
| 66 | uint8_t level; // Notice=0, Info=0x01, Debug=0x02, Error=0x10, Fault=0x11 | ||
| 67 | uint8_t unk07; | ||
| 68 | uint8_t unk08; | ||
| 69 | uint8_t unk09; | ||
| 70 | uint8_t unk10; | ||
| 71 | uint8_t unk11; | ||
| 72 | uint8_t unk12; | ||
| 73 | uint64_t timestamp; // ? | ||
| 74 | uint32_t thread_id; | ||
| 75 | uint32_t unk13; // 0 | ||
| 76 | unsigned char imageuuid[16]; // framework/dylib uuid | ||
| 77 | uint16_t imagepath_len; // framework/dylib | ||
| 78 | uint32_t message_len; // actual log message | ||
| 79 | uint32_t offset; // offset for like timestamp or sth | ||
| 80 | uint16_t subsystem_len; // "subsystem" | ||
| 81 | uint16_t unk14; | ||
| 82 | uint16_t category_len; // "category" | ||
| 83 | uint16_t unk15; | ||
| 84 | uint32_t unk16; // 0 | ||
| 85 | }; | ||
| 86 | #pragma pack(pop) | ||
| 87 | |||
| 88 | /** Receives unparsed ostrace data from the ostrace service */ | ||
| 89 | typedef void (*ostrace_activity_cb_t)(const void* buf, size_t len, void *user_data); | ||
| 90 | |||
| 91 | /** Receives archive data from the ostrace service */ | ||
| 92 | typedef int (*ostrace_archive_write_cb_t)(const void* buf, size_t len, void *user_data); | ||
| 93 | |||
| 94 | /* Interface */ | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Connects to the os_trace_relay service on the specified device. | ||
| 98 | * | ||
| 99 | * @param device The device to connect to. | ||
| 100 | * @param service The service descriptor returned by lockdownd_start_service. | ||
| 101 | * @param client Pointer that will point to a newly allocated | ||
| 102 | * ostrace_client_t upon successful return. Must be freed using | ||
| 103 | * ostrace_client_free() after use. | ||
| 104 | * | ||
| 105 | * @return OSTRACE_E_SUCCESS on success, OSTRACE_E_INVALID_ARG when | ||
| 106 | * client is NULL, or an OSTRACE_E_* error code otherwise. | ||
| 107 | */ | ||
| 108 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_client_new(idevice_t device, lockdownd_service_descriptor_t service, ostrace_client_t * client); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Starts a new os_trace_relay service on the specified device and connects to it. | ||
| 112 | * | ||
| 113 | * @param device The device to connect to. | ||
| 114 | * @param client Pointer that will point to a newly allocated | ||
| 115 | * ostrace_client_t upon successful return. Must be freed using | ||
| 116 | * ostrace_client_free() after use. | ||
| 117 | * @param label The label to use for communication. Usually the program name. | ||
| 118 | * Pass NULL to disable sending the label in requests to lockdownd. | ||
| 119 | * | ||
| 120 | * @return OSTRACE_E_SUCCESS on success, or an OSTRACE_E_* error code otherwise. | ||
| 121 | */ | ||
| 122 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_client_start_service(idevice_t device, ostrace_client_t * client, const char* label); | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Disconnects a ostrace client from the device and frees up the | ||
| 126 | * ostrace client data. | ||
| 127 | * | ||
| 128 | * @param client The ostrace client to disconnect and free. | ||
| 129 | * | ||
| 130 | * @return OSTRACE_E_SUCCESS on success, OSTRACE_E_INVALID_ARG when | ||
| 131 | * client is NULL, or an OSTRACE_E_* error code otherwise. | ||
| 132 | */ | ||
| 133 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_client_free(ostrace_client_t client); | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Starts capturing OS trace activity data of the device using a callback. | ||
| 137 | * | ||
| 138 | * Use ostrace_stop_activity() to stop receiving the ostrace. | ||
| 139 | * | ||
| 140 | * @param client The ostrace client to use | ||
| 141 | * @param options Options dictionary to pass to StartActivity request. | ||
| 142 | * Valid options are MessageFilter (PLIST_INT, default 65535), | ||
| 143 | * Pid (PLIST_INT, default -1), and StreamFlags (PLIST_INT, default 60) | ||
| 144 | * @param callback Callback to receive data from ostrace. | ||
| 145 | * @param user_data Custom pointer passed to the callback function. | ||
| 146 | * @param user_data_free_func Function pointer that will be called when the | ||
| 147 | * activity is stopped to release user_data. Can be NULL for none. | ||
| 148 | * | ||
| 149 | * @return OSTRACE_E_SUCCESS on success, | ||
| 150 | * OSTRACE_E_INVALID_ARG when one or more parameters are | ||
| 151 | * invalid or OSTRACE_E_UNKNOWN_ERROR when an unspecified | ||
| 152 | * error occurs or an ostrace activity has already been started. | ||
| 153 | */ | ||
| 154 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_start_activity(ostrace_client_t client, plist_t options, ostrace_activity_cb_t callback, void* user_data); | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Stops the ostrace activity. | ||
| 158 | * | ||
| 159 | * Use ostrace_start_activity() to start receiving OS trace data. | ||
| 160 | * | ||
| 161 | * @param client The ostrace client to use | ||
| 162 | * | ||
| 163 | * @return OSTRACE_E_SUCCESS on success, | ||
| 164 | * OSTRACE_E_INVALID_ARG when one or more parameters are | ||
| 165 | * invalid or OSTRACE_E_UNKNOWN_ERROR when an unspecified | ||
| 166 | * error occurs or an ostrace activity has already been started. | ||
| 167 | */ | ||
| 168 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_stop_activity(ostrace_client_t client); | ||
| 169 | |||
| 170 | /** | ||
| 171 | * Returns a dictionary with all currently running processes on the device. | ||
| 172 | * | ||
| 173 | * @param client The ostrace client to use | ||
| 174 | * @param list Pointer that will receive an allocated PLIST_DICT structure with the process data | ||
| 175 | * | ||
| 176 | * @return OSTRACE_E_SUCCESS on success, or an OSTRACE_E_* error code otherwise | ||
| 177 | */ | ||
| 178 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_get_pid_list(ostrace_client_t client, plist_t* list); | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Creates a syslog archive. | ||
| 182 | * | ||
| 183 | * @note The device will close the connection once the transfer is complete. The client | ||
| 184 | * is not usable after that anymore and must be disposed with ostrace_client_free. | ||
| 185 | * | ||
| 186 | * @param client The ostrace client to use | ||
| 187 | * @param options A dictionary with options for the request. | ||
| 188 | * Valid parameters are StartTime (PLIST_UINT), SizeLimit (PLIST_UINT), and AgeLimit (PLIST_UINT). | ||
| 189 | * | ||
| 190 | * @return OSTRACE_E_SUCCESS on success, or an OSTRACE_E_* error code otherwise | ||
| 191 | */ | ||
| 192 | LIBIMOBILEDEVICE_API ostrace_error_t ostrace_create_archive(ostrace_client_t client, plist_t options, ostrace_archive_write_cb_t callback, void* user_data); | ||
| 193 | |||
| 194 | #ifdef __cplusplus | ||
| 195 | } | ||
| 196 | #endif | ||
| 197 | |||
| 198 | #endif | ||
diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4 index 44dbd83..935056c 100644 --- a/m4/ax_python_devel.m4 +++ b/m4/ax_python_devel.m4 | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | # | 4 | # |
| 5 | # SYNOPSIS | 5 | # SYNOPSIS |
| 6 | # | 6 | # |
| 7 | # AX_PYTHON_DEVEL([version]) | 7 | # AX_PYTHON_DEVEL([version[,optional]]) |
| 8 | # | 8 | # |
| 9 | # DESCRIPTION | 9 | # DESCRIPTION |
| 10 | # | 10 | # |
| @@ -23,6 +23,11 @@ | |||
| 23 | # version number. Don't use "PYTHON_VERSION" for this: that environment | 23 | # version number. Don't use "PYTHON_VERSION" for this: that environment |
| 24 | # variable is declared as precious and thus reserved for the end-user. | 24 | # variable is declared as precious and thus reserved for the end-user. |
| 25 | # | 25 | # |
| 26 | # By default this will fail if it does not detect a development version of | ||
| 27 | # python. If you want it to continue, set optional to true, like | ||
| 28 | # AX_PYTHON_DEVEL([], [true]). The ax_python_devel_found variable will be | ||
| 29 | # "no" if it fails. | ||
| 30 | # | ||
| 26 | # This macro should work for all versions of Python >= 2.1.0. As an end | 31 | # This macro should work for all versions of Python >= 2.1.0. As an end |
| 27 | # user, you can disable the check for the python version by setting the | 32 | # user, you can disable the check for the python version by setting the |
| 28 | # PYTHON_NOVERSIONCHECK environment variable to something else than the | 33 | # PYTHON_NOVERSIONCHECK environment variable to something else than the |
| @@ -67,10 +72,18 @@ | |||
| 67 | # modified version of the Autoconf Macro, you may extend this special | 72 | # modified version of the Autoconf Macro, you may extend this special |
| 68 | # exception to the GPL to apply to your modified version as well. | 73 | # exception to the GPL to apply to your modified version as well. |
| 69 | 74 | ||
| 70 | #serial 21 | 75 | #serial 37 |
| 71 | 76 | ||
| 72 | AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) | 77 | AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) |
| 73 | AC_DEFUN([AX_PYTHON_DEVEL],[ | 78 | AC_DEFUN([AX_PYTHON_DEVEL],[ |
| 79 | # Get whether it's optional | ||
| 80 | if test -z "$2"; then | ||
| 81 | ax_python_devel_optional=false | ||
| 82 | else | ||
| 83 | ax_python_devel_optional=$2 | ||
| 84 | fi | ||
| 85 | ax_python_devel_found=yes | ||
| 86 | |||
| 74 | # | 87 | # |
| 75 | # Allow the use of a (user set) custom python version | 88 | # Allow the use of a (user set) custom python version |
| 76 | # | 89 | # |
| @@ -81,21 +94,26 @@ AC_DEFUN([AX_PYTHON_DEVEL],[ | |||
| 81 | 94 | ||
| 82 | AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) | 95 | AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) |
| 83 | if test -z "$PYTHON"; then | 96 | if test -z "$PYTHON"; then |
| 84 | AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) | 97 | AC_MSG_WARN([Cannot find python$PYTHON_VERSION in your system path]) |
| 98 | if ! $ax_python_devel_optional; then | ||
| 99 | AC_MSG_ERROR([Giving up, python development not available]) | ||
| 100 | fi | ||
| 101 | ax_python_devel_found=no | ||
| 85 | PYTHON_VERSION="" | 102 | PYTHON_VERSION="" |
| 86 | fi | 103 | fi |
| 87 | 104 | ||
| 88 | # | 105 | if test $ax_python_devel_found = yes; then |
| 89 | # Check for a version of Python >= 2.1.0 | 106 | # |
| 90 | # | 107 | # Check for a version of Python >= 2.1.0 |
| 91 | AC_MSG_CHECKING([for a version of Python >= '2.1.0']) | 108 | # |
| 92 | ac_supports_python_ver=`$PYTHON -c "import sys; \ | 109 | AC_MSG_CHECKING([for a version of Python >= '2.1.0']) |
| 110 | ac_supports_python_ver=`$PYTHON -c "import sys; \ | ||
| 93 | ver = sys.version.split ()[[0]]; \ | 111 | ver = sys.version.split ()[[0]]; \ |
| 94 | print (ver >= '2.1.0')"` | 112 | print (ver >= '2.1.0')"` |
| 95 | if test "$ac_supports_python_ver" != "True"; then | 113 | if test "$ac_supports_python_ver" != "True"; then |
| 96 | if test -z "$PYTHON_NOVERSIONCHECK"; then | 114 | if test -z "$PYTHON_NOVERSIONCHECK"; then |
| 97 | AC_MSG_RESULT([no]) | 115 | AC_MSG_RESULT([no]) |
| 98 | AC_MSG_FAILURE([ | 116 | AC_MSG_WARN([ |
| 99 | This version of the AC@&t@_PYTHON_DEVEL macro | 117 | This version of the AC@&t@_PYTHON_DEVEL macro |
| 100 | doesn't work properly with versions of Python before | 118 | doesn't work properly with versions of Python before |
| 101 | 2.1.0. You may need to re-run configure, setting the | 119 | 2.1.0. You may need to re-run configure, setting the |
| @@ -104,58 +122,119 @@ PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. | |||
| 104 | Moreover, to disable this check, set PYTHON_NOVERSIONCHECK | 122 | Moreover, to disable this check, set PYTHON_NOVERSIONCHECK |
| 105 | to something else than an empty string. | 123 | to something else than an empty string. |
| 106 | ]) | 124 | ]) |
| 125 | if ! $ax_python_devel_optional; then | ||
| 126 | AC_MSG_FAILURE([Giving up]) | ||
| 127 | fi | ||
| 128 | ax_python_devel_found=no | ||
| 129 | PYTHON_VERSION="" | ||
| 107 | else | 130 | else |
| 108 | AC_MSG_RESULT([skip at user request]) | 131 | AC_MSG_RESULT([skip at user request]) |
| 109 | fi | 132 | fi |
| 110 | else | 133 | else |
| 111 | AC_MSG_RESULT([yes]) | 134 | AC_MSG_RESULT([yes]) |
| 135 | fi | ||
| 112 | fi | 136 | fi |
| 113 | 137 | ||
| 114 | # | 138 | if test $ax_python_devel_found = yes; then |
| 115 | # if the macro parameter ``version'' is set, honour it | 139 | # |
| 116 | # | 140 | # If the macro parameter ``version'' is set, honour it. |
| 117 | if test -n "$1"; then | 141 | # A Python shim class, VPy, is used to implement correct version comparisons via |
| 142 | # string expressions, since e.g. a naive textual ">= 2.7.3" won't work for | ||
| 143 | # Python 2.7.10 (the ".1" being evaluated as less than ".3"). | ||
| 144 | # | ||
| 145 | if test -n "$1"; then | ||
| 118 | AC_MSG_CHECKING([for a version of Python $1]) | 146 | AC_MSG_CHECKING([for a version of Python $1]) |
| 119 | ac_supports_python_ver=`$PYTHON -c "import sys; \ | 147 | cat << EOF > ax_python_devel_vpy.py |
| 120 | ver = sys.version.split ()[[0]]; \ | 148 | class VPy: |
| 149 | def vtup(self, s): | ||
| 150 | return tuple(map(int, s.strip().replace("rc", ".").split("."))) | ||
| 151 | def __init__(self): | ||
| 152 | import sys | ||
| 153 | self.vpy = tuple(sys.version_info)[[:3]] | ||
| 154 | def __eq__(self, s): | ||
| 155 | return self.vpy == self.vtup(s) | ||
| 156 | def __ne__(self, s): | ||
| 157 | return self.vpy != self.vtup(s) | ||
| 158 | def __lt__(self, s): | ||
| 159 | return self.vpy < self.vtup(s) | ||
| 160 | def __gt__(self, s): | ||
| 161 | return self.vpy > self.vtup(s) | ||
| 162 | def __le__(self, s): | ||
| 163 | return self.vpy <= self.vtup(s) | ||
| 164 | def __ge__(self, s): | ||
| 165 | return self.vpy >= self.vtup(s) | ||
| 166 | EOF | ||
| 167 | ac_supports_python_ver=`$PYTHON -c "import ax_python_devel_vpy; \ | ||
| 168 | ver = ax_python_devel_vpy.VPy(); \ | ||
| 121 | print (ver $1)"` | 169 | print (ver $1)"` |
| 170 | rm -rf ax_python_devel_vpy*.py* __pycache__/ax_python_devel_vpy*.py* | ||
| 122 | if test "$ac_supports_python_ver" = "True"; then | 171 | if test "$ac_supports_python_ver" = "True"; then |
| 123 | AC_MSG_RESULT([yes]) | 172 | AC_MSG_RESULT([yes]) |
| 124 | else | 173 | else |
| 125 | AC_MSG_RESULT([no]) | 174 | AC_MSG_RESULT([no]) |
| 126 | AC_MSG_ERROR([this package requires Python $1. | 175 | AC_MSG_WARN([this package requires Python $1. |
| 127 | If you have it installed, but it isn't the default Python | 176 | If you have it installed, but it isn't the default Python |
| 128 | interpreter in your system path, please pass the PYTHON_VERSION | 177 | interpreter in your system path, please pass the PYTHON_VERSION |
| 129 | variable to configure. See ``configure --help'' for reference. | 178 | variable to configure. See ``configure --help'' for reference. |
| 130 | ]) | 179 | ]) |
| 180 | if ! $ax_python_devel_optional; then | ||
| 181 | AC_MSG_ERROR([Giving up]) | ||
| 182 | fi | ||
| 183 | ax_python_devel_found=no | ||
| 131 | PYTHON_VERSION="" | 184 | PYTHON_VERSION="" |
| 132 | fi | 185 | fi |
| 186 | fi | ||
| 133 | fi | 187 | fi |
| 134 | 188 | ||
| 135 | # | 189 | if test $ax_python_devel_found = yes; then |
| 136 | # Check if you have distutils, else fail | 190 | # |
| 137 | # | 191 | # Check if you have distutils, else fail |
| 138 | AC_MSG_CHECKING([for the distutils Python package]) | 192 | # |
| 139 | ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` | 193 | AC_MSG_CHECKING([for the sysconfig Python package]) |
| 140 | if test $? -eq 0; then | 194 | ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1` |
| 195 | if test $? -eq 0; then | ||
| 141 | AC_MSG_RESULT([yes]) | 196 | AC_MSG_RESULT([yes]) |
| 142 | else | 197 | IMPORT_SYSCONFIG="import sysconfig" |
| 198 | else | ||
| 143 | AC_MSG_RESULT([no]) | 199 | AC_MSG_RESULT([no]) |
| 144 | AC_MSG_ERROR([cannot import Python module "distutils". | 200 | |
| 201 | AC_MSG_CHECKING([for the distutils Python package]) | ||
| 202 | ac_sysconfig_result=`$PYTHON -c "from distutils import sysconfig" 2>&1` | ||
| 203 | if test $? -eq 0; then | ||
| 204 | AC_MSG_RESULT([yes]) | ||
| 205 | IMPORT_SYSCONFIG="from distutils import sysconfig" | ||
| 206 | else | ||
| 207 | AC_MSG_WARN([cannot import Python module "distutils". | ||
| 145 | Please check your Python installation. The error was: | 208 | Please check your Python installation. The error was: |
| 146 | $ac_distutils_result]) | 209 | $ac_sysconfig_result]) |
| 147 | PYTHON_VERSION="" | 210 | if ! $ax_python_devel_optional; then |
| 211 | AC_MSG_ERROR([Giving up]) | ||
| 212 | fi | ||
| 213 | ax_python_devel_found=no | ||
| 214 | PYTHON_VERSION="" | ||
| 215 | fi | ||
| 216 | fi | ||
| 148 | fi | 217 | fi |
| 149 | 218 | ||
| 150 | # | 219 | if test $ax_python_devel_found = yes; then |
| 151 | # Check for Python include path | 220 | # |
| 152 | # | 221 | # Check for Python include path |
| 153 | AC_MSG_CHECKING([for Python include path]) | 222 | # |
| 154 | if test -z "$PYTHON_CPPFLAGS"; then | 223 | AC_MSG_CHECKING([for Python include path]) |
| 155 | python_path=`$PYTHON -c "import distutils.sysconfig; \ | 224 | if test -z "$PYTHON_CPPFLAGS"; then |
| 156 | print (distutils.sysconfig.get_python_inc ());"` | 225 | if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then |
| 157 | plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ | 226 | # sysconfig module has different functions |
| 158 | print (distutils.sysconfig.get_python_inc (plat_specific=1));"` | 227 | python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \ |
| 228 | print (sysconfig.get_path ('include'));"` | ||
| 229 | plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 230 | print (sysconfig.get_path ('platinclude'));"` | ||
| 231 | else | ||
| 232 | # old distutils way | ||
| 233 | python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 234 | print (sysconfig.get_python_inc ());"` | ||
| 235 | plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 236 | print (sysconfig.get_python_inc (plat_specific=1));"` | ||
| 237 | fi | ||
| 159 | if test -n "${python_path}"; then | 238 | if test -n "${python_path}"; then |
| 160 | if test "${plat_python_path}" != "${python_path}"; then | 239 | if test "${plat_python_path}" != "${python_path}"; then |
| 161 | python_path="-I$python_path -I$plat_python_path" | 240 | python_path="-I$python_path -I$plat_python_path" |
| @@ -164,22 +243,22 @@ $ac_distutils_result]) | |||
| 164 | fi | 243 | fi |
| 165 | fi | 244 | fi |
| 166 | PYTHON_CPPFLAGS=$python_path | 245 | PYTHON_CPPFLAGS=$python_path |
| 167 | fi | 246 | fi |
| 168 | AC_MSG_RESULT([$PYTHON_CPPFLAGS]) | 247 | AC_MSG_RESULT([$PYTHON_CPPFLAGS]) |
| 169 | AC_SUBST([PYTHON_CPPFLAGS]) | 248 | AC_SUBST([PYTHON_CPPFLAGS]) |
| 170 | 249 | ||
| 171 | # | 250 | # |
| 172 | # Check for Python library path | 251 | # Check for Python library path |
| 173 | # | 252 | # |
| 174 | AC_MSG_CHECKING([for Python library path]) | 253 | AC_MSG_CHECKING([for Python library path]) |
| 175 | if test -z "$PYTHON_LIBS"; then | 254 | if test -z "$PYTHON_LIBS"; then |
| 176 | # (makes two attempts to ensure we've got a version number | 255 | # (makes two attempts to ensure we've got a version number |
| 177 | # from the interpreter) | 256 | # from the interpreter) |
| 178 | ac_python_version=`cat<<EOD | $PYTHON - | 257 | ac_python_version=`cat<<EOD | $PYTHON - |
| 179 | 258 | ||
| 180 | # join all versioning strings, on some systems | 259 | # join all versioning strings, on some systems |
| 181 | # major/minor numbers could be in different list elements | 260 | # major/minor numbers could be in different list elements |
| 182 | from distutils.sysconfig import * | 261 | from sysconfig import * |
| 183 | e = get_config_var('VERSION') | 262 | e = get_config_var('VERSION') |
| 184 | if e is not None: | 263 | if e is not None: |
| 185 | print(e) | 264 | print(e) |
| @@ -190,7 +269,7 @@ EOD` | |||
| 190 | ac_python_version=$PYTHON_VERSION | 269 | ac_python_version=$PYTHON_VERSION |
| 191 | else | 270 | else |
| 192 | ac_python_version=`$PYTHON -c "import sys; \ | 271 | ac_python_version=`$PYTHON -c "import sys; \ |
| 193 | print (sys.version[[:3]])"` | 272 | print ("%d.%d" % sys.version_info[[:2]])"` |
| 194 | fi | 273 | fi |
| 195 | fi | 274 | fi |
| 196 | 275 | ||
| @@ -202,8 +281,8 @@ EOD` | |||
| 202 | ac_python_libdir=`cat<<EOD | $PYTHON - | 281 | ac_python_libdir=`cat<<EOD | $PYTHON - |
| 203 | 282 | ||
| 204 | # There should be only one | 283 | # There should be only one |
| 205 | import distutils.sysconfig | 284 | $IMPORT_SYSCONFIG |
| 206 | e = distutils.sysconfig.get_config_var('LIBDIR') | 285 | e = sysconfig.get_config_var('LIBDIR') |
| 207 | if e is not None: | 286 | if e is not None: |
| 208 | print (e) | 287 | print (e) |
| 209 | EOD` | 288 | EOD` |
| @@ -211,8 +290,8 @@ EOD` | |||
| 211 | # Now, for the library: | 290 | # Now, for the library: |
| 212 | ac_python_library=`cat<<EOD | $PYTHON - | 291 | ac_python_library=`cat<<EOD | $PYTHON - |
| 213 | 292 | ||
| 214 | import distutils.sysconfig | 293 | $IMPORT_SYSCONFIG |
| 215 | c = distutils.sysconfig.get_config_vars() | 294 | c = sysconfig.get_config_vars() |
| 216 | if 'LDVERSION' in c: | 295 | if 'LDVERSION' in c: |
| 217 | print ('python'+c[['LDVERSION']]) | 296 | print ('python'+c[['LDVERSION']]) |
| 218 | else: | 297 | else: |
| @@ -231,83 +310,140 @@ EOD` | |||
| 231 | else | 310 | else |
| 232 | # old way: use libpython from python_configdir | 311 | # old way: use libpython from python_configdir |
| 233 | ac_python_libdir=`$PYTHON -c \ | 312 | ac_python_libdir=`$PYTHON -c \ |
| 234 | "from distutils.sysconfig import get_python_lib as f; \ | 313 | "from sysconfig import get_python_lib as f; \ |
| 235 | import os; \ | 314 | import os; \ |
| 236 | print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"` | 315 | print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"` |
| 237 | PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version" | 316 | PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version" |
| 238 | fi | 317 | fi |
| 239 | 318 | ||
| 240 | if test -z "PYTHON_LIBS"; then | 319 | if test -z "$PYTHON_LIBS"; then |
| 241 | AC_MSG_ERROR([ | 320 | AC_MSG_WARN([ |
| 242 | Cannot determine location of your Python DSO. Please check it was installed with | 321 | Cannot determine location of your Python DSO. Please check it was installed with |
| 243 | dynamic libraries enabled, or try setting PYTHON_LIBS by hand. | 322 | dynamic libraries enabled, or try setting PYTHON_LIBS by hand. |
| 244 | ]) | 323 | ]) |
| 324 | if ! $ax_python_devel_optional; then | ||
| 325 | AC_MSG_ERROR([Giving up]) | ||
| 326 | fi | ||
| 327 | ax_python_devel_found=no | ||
| 328 | PYTHON_VERSION="" | ||
| 245 | fi | 329 | fi |
| 330 | fi | ||
| 246 | fi | 331 | fi |
| 247 | AC_MSG_RESULT([$PYTHON_LIBS]) | ||
| 248 | AC_SUBST([PYTHON_LIBS]) | ||
| 249 | 332 | ||
| 250 | # | 333 | if test $ax_python_devel_found = yes; then |
| 251 | # Check for site packages | 334 | AC_MSG_RESULT([$PYTHON_LIBS]) |
| 252 | # | 335 | AC_SUBST([PYTHON_LIBS]) |
| 253 | AC_MSG_CHECKING([for Python site-packages path]) | ||
| 254 | if test -z "$PYTHON_SITE_PKG"; then | ||
| 255 | PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ | ||
| 256 | print (distutils.sysconfig.get_python_lib(0,0));"` | ||
| 257 | fi | ||
| 258 | AC_MSG_RESULT([$PYTHON_SITE_PKG]) | ||
| 259 | AC_SUBST([PYTHON_SITE_PKG]) | ||
| 260 | 336 | ||
| 261 | # | 337 | # |
| 262 | # libraries which must be linked in when embedding | 338 | # Check for site packages |
| 263 | # | 339 | # |
| 264 | AC_MSG_CHECKING(python extra libraries) | 340 | AC_MSG_CHECKING([for Python site-packages path]) |
| 265 | if test -z "$PYTHON_EXTRA_LIBS"; then | 341 | if test -z "$PYTHON_SITE_PKG"; then |
| 266 | PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ | 342 | if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then |
| 267 | conf = distutils.sysconfig.get_config_var; \ | 343 | PYTHON_SITE_PKG=`$PYTHON -c " |
| 344 | $IMPORT_SYSCONFIG; | ||
| 345 | if hasattr(sysconfig, 'get_default_scheme'): | ||
| 346 | scheme = sysconfig.get_default_scheme() | ||
| 347 | else: | ||
| 348 | scheme = sysconfig._get_default_scheme() | ||
| 349 | if scheme == 'posix_local': | ||
| 350 | # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ | ||
| 351 | scheme = 'posix_prefix' | ||
| 352 | prefix = '$prefix' | ||
| 353 | if prefix == 'NONE': | ||
| 354 | prefix = '$ac_default_prefix' | ||
| 355 | sitedir = sysconfig.get_path('purelib', scheme, vars={'base': prefix}) | ||
| 356 | print(sitedir)"` | ||
| 357 | else | ||
| 358 | # distutils.sysconfig way | ||
| 359 | PYTHON_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 360 | print (sysconfig.get_python_lib(0,0));"` | ||
| 361 | fi | ||
| 362 | fi | ||
| 363 | AC_MSG_RESULT([$PYTHON_SITE_PKG]) | ||
| 364 | AC_SUBST([PYTHON_SITE_PKG]) | ||
| 365 | |||
| 366 | # | ||
| 367 | # Check for platform-specific site packages | ||
| 368 | # | ||
| 369 | AC_MSG_CHECKING([for Python platform specific site-packages path]) | ||
| 370 | if test -z "$PYTHON_PLATFORM_SITE_PKG"; then | ||
| 371 | if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then | ||
| 372 | PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c " | ||
| 373 | $IMPORT_SYSCONFIG; | ||
| 374 | if hasattr(sysconfig, 'get_default_scheme'): | ||
| 375 | scheme = sysconfig.get_default_scheme() | ||
| 376 | else: | ||
| 377 | scheme = sysconfig._get_default_scheme() | ||
| 378 | if scheme == 'posix_local': | ||
| 379 | # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ | ||
| 380 | scheme = 'posix_prefix' | ||
| 381 | prefix = '$prefix' | ||
| 382 | if prefix == 'NONE': | ||
| 383 | prefix = '$ac_default_prefix' | ||
| 384 | sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase': prefix}) | ||
| 385 | print(sitedir)"` | ||
| 386 | else | ||
| 387 | # distutils.sysconfig way | ||
| 388 | PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 389 | print (sysconfig.get_python_lib(1,0));"` | ||
| 390 | fi | ||
| 391 | fi | ||
| 392 | AC_MSG_RESULT([$PYTHON_PLATFORM_SITE_PKG]) | ||
| 393 | AC_SUBST([PYTHON_PLATFORM_SITE_PKG]) | ||
| 394 | |||
| 395 | # | ||
| 396 | # libraries which must be linked in when embedding | ||
| 397 | # | ||
| 398 | AC_MSG_CHECKING(python extra libraries) | ||
| 399 | if test -z "$PYTHON_EXTRA_LIBS"; then | ||
| 400 | PYTHON_EXTRA_LIBS=`$PYTHON -c "$IMPORT_SYSCONFIG; \ | ||
| 401 | conf = sysconfig.get_config_var; \ | ||
| 268 | print (conf('LIBS') + ' ' + conf('SYSLIBS'))"` | 402 | print (conf('LIBS') + ' ' + conf('SYSLIBS'))"` |
| 269 | fi | 403 | fi |
| 270 | AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) | 404 | AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) |
| 271 | AC_SUBST(PYTHON_EXTRA_LIBS) | 405 | AC_SUBST(PYTHON_EXTRA_LIBS) |
| 272 | 406 | ||
| 273 | # | 407 | # |
| 274 | # linking flags needed when embedding | 408 | # linking flags needed when embedding |
| 275 | # | 409 | # |
| 276 | AC_MSG_CHECKING(python extra linking flags) | 410 | AC_MSG_CHECKING(python extra linking flags) |
| 277 | if test -z "$PYTHON_EXTRA_LDFLAGS"; then | 411 | if test -z "$PYTHON_EXTRA_LDFLAGS"; then |
| 278 | PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ | 412 | PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "$IMPORT_SYSCONFIG; \ |
| 279 | conf = distutils.sysconfig.get_config_var; \ | 413 | conf = sysconfig.get_config_var; \ |
| 280 | print (conf('LINKFORSHARED'))"` | 414 | print (conf('LINKFORSHARED'))"` |
| 281 | fi | 415 | # Hack for macos, it sticks this in here. |
| 282 | AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) | 416 | PYTHON_EXTRA_LDFLAGS=`echo $PYTHON_EXTRA_LDFLAGS | sed 's/CoreFoundation.*$/CoreFoundation/'` |
| 283 | AC_SUBST(PYTHON_EXTRA_LDFLAGS) | 417 | fi |
| 418 | AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) | ||
| 419 | AC_SUBST(PYTHON_EXTRA_LDFLAGS) | ||
| 284 | 420 | ||
| 285 | # | 421 | # |
| 286 | # final check to see if everything compiles alright | 422 | # final check to see if everything compiles alright |
| 287 | # | 423 | # |
| 288 | AC_MSG_CHECKING([consistency of all components of python development environment]) | 424 | AC_MSG_CHECKING([consistency of all components of python development environment]) |
| 289 | # save current global flags | 425 | # save current global flags |
| 290 | ac_save_LIBS="$LIBS" | 426 | ac_save_LIBS="$LIBS" |
| 291 | ac_save_LDFLAGS="$LDFLAGS" | 427 | ac_save_LDFLAGS="$LDFLAGS" |
| 292 | ac_save_CPPFLAGS="$CPPFLAGS" | 428 | ac_save_CPPFLAGS="$CPPFLAGS" |
| 293 | LIBS="$ac_save_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_EXTRA_LIBS" | 429 | LIBS="$ac_save_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS" |
| 294 | LDFLAGS="$ac_save_LDFLAGS $PYTHON_EXTRA_LDFLAGS" | 430 | LDFLAGS="$ac_save_LDFLAGS $PYTHON_EXTRA_LDFLAGS" |
| 295 | CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" | 431 | CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" |
| 296 | AC_LANG_PUSH([C]) | 432 | AC_LANG_PUSH([C]) |
| 297 | AC_LINK_IFELSE([ | 433 | AC_LINK_IFELSE([ |
| 298 | AC_LANG_PROGRAM([[#include <Python.h>]], | 434 | AC_LANG_PROGRAM([[#include <Python.h>]], |
| 299 | [[Py_Initialize();]]) | 435 | [[Py_Initialize();]]) |
| 300 | ],[pythonexists=yes],[pythonexists=no]) | 436 | ],[pythonexists=yes],[pythonexists=no]) |
| 301 | AC_LANG_POP([C]) | 437 | AC_LANG_POP([C]) |
| 302 | # turn back to default flags | 438 | # turn back to default flags |
| 303 | CPPFLAGS="$ac_save_CPPFLAGS" | 439 | CPPFLAGS="$ac_save_CPPFLAGS" |
| 304 | LIBS="$ac_save_LIBS" | 440 | LIBS="$ac_save_LIBS" |
| 305 | LDFLAGS="$ac_save_LDFLAGS" | 441 | LDFLAGS="$ac_save_LDFLAGS" |
| 306 | 442 | ||
| 307 | AC_MSG_RESULT([$pythonexists]) | 443 | AC_MSG_RESULT([$pythonexists]) |
| 308 | 444 | ||
| 309 | if test ! "x$pythonexists" = "xyes"; then | 445 | if test ! "x$pythonexists" = "xyes"; then |
| 310 | AC_MSG_FAILURE([ | 446 | AC_MSG_WARN([ |
| 311 | Could not link test program to Python. Maybe the main Python library has been | 447 | Could not link test program to Python. Maybe the main Python library has been |
| 312 | installed in some non-standard library path. If so, pass it to configure, | 448 | installed in some non-standard library path. If so, pass it to configure, |
| 313 | via the LIBS environment variable. | 449 | via the LIBS environment variable. |
| @@ -317,8 +453,13 @@ EOD` | |||
| 317 | You probably have to install the development version of the Python package | 453 | You probably have to install the development version of the Python package |
| 318 | for your distribution. The exact name of this package varies among them. | 454 | for your distribution. The exact name of this package varies among them. |
| 319 | ============================================================================ | 455 | ============================================================================ |
| 320 | ]) | 456 | ]) |
| 321 | PYTHON_VERSION="" | 457 | if ! $ax_python_devel_optional; then |
| 458 | AC_MSG_ERROR([Giving up]) | ||
| 459 | fi | ||
| 460 | ax_python_devel_found=no | ||
| 461 | PYTHON_VERSION="" | ||
| 462 | fi | ||
| 322 | fi | 463 | fi |
| 323 | 464 | ||
| 324 | # | 465 | # |
diff --git a/src/Makefile.am b/src/Makefile.am index 58cf07c..1ee9be8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
| @@ -58,6 +58,7 @@ libimobiledevice_1_0_la_SOURCES = \ | |||
| 58 | companion_proxy.c companion_proxy.h \ | 58 | companion_proxy.c companion_proxy.h \ |
| 59 | reverse_proxy.c reverse_proxy.h \ | 59 | reverse_proxy.c reverse_proxy.h \ |
| 60 | syslog_relay.c syslog_relay.h \ | 60 | syslog_relay.c syslog_relay.h \ |
| 61 | ostrace.c ostrace.h \ | ||
| 61 | bt_packet_logger.c bt_packet_logger.h | 62 | bt_packet_logger.c bt_packet_logger.h |
| 62 | 63 | ||
| 63 | if WIN32 | 64 | if WIN32 |
| @@ -26,9 +26,12 @@ | |||
| 26 | #endif | 26 | #endif |
| 27 | #include <stdio.h> | 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> | 28 | #include <stdlib.h> |
| 29 | #include <unistd.h> | ||
| 30 | #include <string.h> | 29 | #include <string.h> |
| 31 | 30 | ||
| 31 | #ifndef _MSC_VER | ||
| 32 | #include <unistd.h> | ||
| 33 | #endif | ||
| 34 | |||
| 32 | #include "idevice.h" | 35 | #include "idevice.h" |
| 33 | #include "afc.h" | 36 | #include "afc.h" |
| 34 | #include "common/debug.h" | 37 | #include "common/debug.h" |
| @@ -56,6 +59,27 @@ static void afc_unlock(afc_client_t client) | |||
| 56 | mutex_unlock(&client->mutex); | 59 | mutex_unlock(&client->mutex); |
| 57 | } | 60 | } |
| 58 | 61 | ||
| 62 | static afc_error_t service_to_afc_error(service_error_t err) | ||
| 63 | { | ||
| 64 | switch (err) { | ||
| 65 | case SERVICE_E_SUCCESS: | ||
| 66 | return AFC_E_SUCCESS; | ||
| 67 | case SERVICE_E_INVALID_ARG: | ||
| 68 | return AFC_E_INVALID_ARG; | ||
| 69 | case SERVICE_E_MUX_ERROR: | ||
| 70 | return AFC_E_MUX_ERROR; | ||
| 71 | case SERVICE_E_SSL_ERROR: | ||
| 72 | return AFC_E_SSL_ERROR; | ||
| 73 | case SERVICE_E_NOT_ENOUGH_DATA: | ||
| 74 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 75 | case SERVICE_E_TIMEOUT: | ||
| 76 | return AFC_E_OP_TIMEOUT; | ||
| 77 | default: | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | return AFC_E_UNKNOWN_ERROR; | ||
| 81 | } | ||
| 82 | |||
| 59 | /** | 83 | /** |
| 60 | * Makes a connection to the AFC service on the device using the given | 84 | * Makes a connection to the AFC service on the device using the given |
| 61 | * connection. | 85 | * connection. |
| @@ -115,7 +139,7 @@ afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t serv | |||
| 115 | 139 | ||
| 116 | afc_error_t afc_client_start_service(idevice_t device, afc_client_t * client, const char* label) | 140 | afc_error_t afc_client_start_service(idevice_t device, afc_client_t * client, const char* label) |
| 117 | { | 141 | { |
| 118 | afc_error_t err = AFC_E_UNKNOWN_ERROR; | 142 | int32_t err = AFC_E_UNKNOWN_ERROR; |
| 119 | service_client_factory_start_service(device, AFC_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(afc_client_new), &err); | 143 | service_client_factory_start_service(device, AFC_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(afc_client_new), &err); |
| 120 | return err; | 144 | return err; |
| 121 | } | 145 | } |
| @@ -171,11 +195,16 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation, | |||
| 171 | AFCPacket_to_LE(client->afc_packet); | 195 | AFCPacket_to_LE(client->afc_packet); |
| 172 | debug_buffer((char*)client->afc_packet, sizeof(AFCPacket) + data_length); | 196 | debug_buffer((char*)client->afc_packet, sizeof(AFCPacket) + data_length); |
| 173 | sent = 0; | 197 | sent = 0; |
| 174 | service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket) + data_length, &sent); | 198 | afc_error_t err = service_to_afc_error(service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket) + data_length, &sent)); |
| 175 | AFCPacket_from_LE(client->afc_packet); | 199 | AFCPacket_from_LE(client->afc_packet); |
| 200 | if (err != AFC_E_SUCCESS) { | ||
| 201 | debug_info("Failed to send packet (sent %i/%i): %s (%d)", sent, sizeof(AFCPacket) + data_length, afc_strerror(err), err); | ||
| 202 | return err; | ||
| 203 | } | ||
| 176 | *bytes_sent += sent; | 204 | *bytes_sent += sent; |
| 177 | if (sent < sizeof(AFCPacket) + data_length) { | 205 | if (sent < sizeof(AFCPacket) + data_length) { |
| 178 | return AFC_E_SUCCESS; | 206 | debug_info("Failed to send entire packet (sent %i/%i)", sent, sizeof(AFCPacket) + data_length); |
| 207 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 179 | } | 208 | } |
| 180 | 209 | ||
| 181 | sent = 0; | 210 | sent = 0; |
| @@ -187,11 +216,16 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, uint64_t operation, | |||
| 187 | debug_info("packet payload follows"); | 216 | debug_info("packet payload follows"); |
| 188 | debug_buffer(payload, payload_length); | 217 | debug_buffer(payload, payload_length); |
| 189 | } | 218 | } |
| 190 | service_send(client->parent, payload, payload_length, &sent); | 219 | err = service_to_afc_error(service_send(client->parent, payload, payload_length, &sent)); |
| 220 | if (err != AFC_E_SUCCESS) { | ||
| 221 | debug_info("Failed to send payload (sent: %i/%i): %s (%d)", sent, payload_length, afc_strerror(err), err); | ||
| 222 | return err; | ||
| 223 | } | ||
| 191 | } | 224 | } |
| 192 | *bytes_sent += sent; | 225 | *bytes_sent += sent; |
| 193 | if (sent < payload_length) { | 226 | if (sent < payload_length) { |
| 194 | return AFC_E_SUCCESS; | 227 | debug_info("Failed to send entire payload (sent: %i/%i): %s (%d)", sent, payload_length, afc_strerror(err), err); |
| 228 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 195 | } | 229 | } |
| 196 | 230 | ||
| 197 | return AFC_E_SUCCESS; | 231 | return AFC_E_SUCCESS; |
| @@ -224,21 +258,28 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t | |||
| 224 | } | 258 | } |
| 225 | 259 | ||
| 226 | /* first, read the AFC header */ | 260 | /* first, read the AFC header */ |
| 227 | service_receive(client->parent, (char*)&header, sizeof(AFCPacket), &recv_len); | 261 | afc_error_t err = service_to_afc_error(service_receive(client->parent, (char*)&header, sizeof(AFCPacket), &recv_len)); |
| 228 | AFCPacket_from_LE(&header); | 262 | if (err != AFC_E_SUCCESS) { |
| 263 | debug_info("Failed to receive AFC header: %s (%d)", afc_strerror(err), err); | ||
| 264 | return err; | ||
| 265 | } | ||
| 229 | if (recv_len == 0) { | 266 | if (recv_len == 0) { |
| 230 | debug_info("Just didn't get enough."); | 267 | debug_info("Just didn't get enough."); |
| 231 | return AFC_E_MUX_ERROR; | 268 | return AFC_E_NOT_ENOUGH_DATA; |
| 232 | } | 269 | } |
| 233 | 270 | ||
| 234 | if (recv_len < sizeof(AFCPacket)) { | 271 | if (recv_len < sizeof(AFCPacket)) { |
| 235 | debug_info("Did not even get the AFCPacket header"); | 272 | debug_info("Did not even get the AFCPacket header"); |
| 236 | return AFC_E_MUX_ERROR; | 273 | return AFC_E_NOT_ENOUGH_DATA; |
| 237 | } | 274 | } |
| 238 | 275 | ||
| 276 | /* make sure endianness is correct */ | ||
| 277 | AFCPacket_from_LE(&header); | ||
| 278 | |||
| 239 | /* check if it's a valid AFC header */ | 279 | /* check if it's a valid AFC header */ |
| 240 | if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN) != 0) { | 280 | if (strncmp(header.magic, AFC_MAGIC, AFC_MAGIC_LEN) != 0) { |
| 241 | debug_info("Invalid AFC packet received (magic != " AFC_MAGIC ")!"); | 281 | debug_info("Invalid AFC packet received (magic != " AFC_MAGIC ")!"); |
| 282 | return AFC_E_UNKNOWN_PACKET_TYPE; | ||
| 242 | } | 283 | } |
| 243 | 284 | ||
| 244 | /* check if it has the correct packet number */ | 285 | /* check if it has the correct packet number */ |
| @@ -270,16 +311,20 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t | |||
| 270 | buf = (char*)malloc(entire_len); | 311 | buf = (char*)malloc(entire_len); |
| 271 | if (this_len > 0) { | 312 | if (this_len > 0) { |
| 272 | recv_len = 0; | 313 | recv_len = 0; |
| 273 | service_receive(client->parent, buf, this_len, &recv_len); | 314 | err = service_to_afc_error(service_receive(client->parent, buf, this_len, &recv_len)); |
| 315 | if (err != AFC_E_SUCCESS) { | ||
| 316 | free(buf); | ||
| 317 | debug_info("Failed to receive data: %s (%d)", afc_strerror(err), err); | ||
| 318 | } | ||
| 274 | if (recv_len <= 0) { | 319 | if (recv_len <= 0) { |
| 275 | free(buf); | 320 | free(buf); |
| 276 | debug_info("Did not get packet contents!"); | 321 | debug_info("Did not get packet contents!"); |
| 277 | return AFC_E_NOT_ENOUGH_DATA; | 322 | return (err == AFC_E_SUCCESS) ? AFC_E_NOT_ENOUGH_DATA : err; |
| 278 | } | 323 | } |
| 279 | if (recv_len < this_len) { | 324 | if (recv_len < this_len) { |
| 280 | free(buf); | 325 | free(buf); |
| 281 | debug_info("Could not receive this_len=%d bytes", this_len); | 326 | debug_info("Could not receive this_len=%d bytes", this_len); |
| 282 | return AFC_E_NOT_ENOUGH_DATA; | 327 | return (err == AFC_E_SUCCESS) ? AFC_E_END_OF_DATA : err; |
| 283 | } | 328 | } |
| 284 | } | 329 | } |
| 285 | 330 | ||
| @@ -288,7 +333,11 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t | |||
| 288 | if (entire_len > this_len) { | 333 | if (entire_len > this_len) { |
| 289 | while (current_count < entire_len) { | 334 | while (current_count < entire_len) { |
| 290 | recv_len = 0; | 335 | recv_len = 0; |
| 291 | service_receive(client->parent, buf+current_count, entire_len - current_count, &recv_len); | 336 | err = service_to_afc_error(service_receive(client->parent, buf+current_count, entire_len - current_count, &recv_len)); |
| 337 | if (err != AFC_E_SUCCESS) { | ||
| 338 | debug_info("Error receiving data: %s (%d)", afc_strerror(err), err); | ||
| 339 | break; | ||
| 340 | } | ||
| 292 | if (recv_len <= 0) { | 341 | if (recv_len <= 0) { |
| 293 | debug_info("Error receiving data (recv returned %d)", recv_len); | 342 | debug_info("Error receiving data (recv returned %d)", recv_len); |
| 294 | break; | 343 | break; |
| @@ -296,7 +345,9 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t | |||
| 296 | current_count += recv_len; | 345 | current_count += recv_len; |
| 297 | } | 346 | } |
| 298 | if (current_count < entire_len) { | 347 | if (current_count < entire_len) { |
| 299 | debug_info("WARNING: could not receive full packet (read %s, size %d)", current_count, entire_len); | 348 | free(buf); |
| 349 | debug_info("ERROR: Could not receive entire packet (read %i/%i)", current_count, entire_len); | ||
| 350 | return (err == AFC_E_SUCCESS) ? AFC_E_END_OF_DATA : err; | ||
| 300 | } | 351 | } |
| 301 | } | 352 | } |
| 302 | 353 | ||
| @@ -338,7 +389,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **bytes, uint32_t | |||
| 338 | free(buf); | 389 | free(buf); |
| 339 | 390 | ||
| 340 | debug_info("WARNING: Unknown operation code received 0x%llx param1=%lld", header.operation, param1); | 391 | debug_info("WARNING: Unknown operation code received 0x%llx param1=%lld", header.operation, param1); |
| 341 | #ifndef WIN32 | 392 | #ifndef _WIN32 |
| 342 | fprintf(stderr, "%s: WARNING: Unknown operation code received 0x%llx param1=%lld", __func__, (long long)header.operation, (long long)param1); | 393 | fprintf(stderr, "%s: WARNING: Unknown operation code received 0x%llx param1=%lld", __func__, (long long)header.operation, (long long)param1); |
| 343 | #endif | 394 | #endif |
| 344 | 395 | ||
| @@ -399,6 +450,50 @@ static char **make_strings_list(char *tokens, uint32_t length) | |||
| 399 | return list; | 450 | return list; |
| 400 | } | 451 | } |
| 401 | 452 | ||
| 453 | static plist_t *make_dictionary(char *tokens, size_t length) | ||
| 454 | { | ||
| 455 | size_t j = 0; | ||
| 456 | plist_t dict = NULL; | ||
| 457 | |||
| 458 | if (!tokens || !length) | ||
| 459 | return NULL; | ||
| 460 | |||
| 461 | dict = plist_new_dict(); | ||
| 462 | |||
| 463 | while (j < length) { | ||
| 464 | size_t key_len = strnlen(tokens + j, length - j); | ||
| 465 | if (j + key_len >= length) { | ||
| 466 | plist_free(dict); | ||
| 467 | return NULL; | ||
| 468 | } | ||
| 469 | char* key = tokens + j; | ||
| 470 | j += key_len + 1; | ||
| 471 | |||
| 472 | if (j >= length) { | ||
| 473 | plist_free(dict); | ||
| 474 | return NULL; | ||
| 475 | } | ||
| 476 | |||
| 477 | size_t val_len = strnlen(tokens + j, length - j); | ||
| 478 | if (j + val_len >= length) { | ||
| 479 | plist_free(dict); | ||
| 480 | return NULL; | ||
| 481 | } | ||
| 482 | char* val = tokens + j; | ||
| 483 | j += val_len + 1; | ||
| 484 | |||
| 485 | char* endp = NULL; | ||
| 486 | unsigned long long u64val = strtoull(val, &endp, 10); | ||
| 487 | if (endp && *endp == '\0') { | ||
| 488 | plist_dict_set_item(dict, key, plist_new_uint(u64val)); | ||
| 489 | } else { | ||
| 490 | plist_dict_set_item(dict, key, plist_new_string(val)); | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 494 | return dict; | ||
| 495 | } | ||
| 496 | |||
| 402 | static int _afc_check_packet_buffer(afc_client_t client, uint32_t data_len) | 497 | static int _afc_check_packet_buffer(afc_client_t client, uint32_t data_len) |
| 403 | { | 498 | { |
| 404 | if (data_len > client->packet_extra) { | 499 | if (data_len > client->packet_extra) { |
| @@ -495,6 +590,40 @@ afc_error_t afc_get_device_info(afc_client_t client, char ***device_information) | |||
| 495 | return ret; | 590 | return ret; |
| 496 | } | 591 | } |
| 497 | 592 | ||
| 593 | afc_error_t afc_get_device_info_plist(afc_client_t client, plist_t *device_information) | ||
| 594 | { | ||
| 595 | uint32_t bytes = 0; | ||
| 596 | char *data = NULL; | ||
| 597 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 598 | |||
| 599 | if (!client || !device_information) | ||
| 600 | return AFC_E_INVALID_ARG; | ||
| 601 | |||
| 602 | afc_lock(client); | ||
| 603 | |||
| 604 | /* Send the command */ | ||
| 605 | ret = afc_dispatch_packet(client, AFC_OP_GET_DEVINFO, 0, NULL, 0, &bytes); | ||
| 606 | if (ret != AFC_E_SUCCESS) { | ||
| 607 | afc_unlock(client); | ||
| 608 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 609 | } | ||
| 610 | /* Receive the data */ | ||
| 611 | ret = afc_receive_data(client, &data, &bytes); | ||
| 612 | if (ret != AFC_E_SUCCESS) { | ||
| 613 | if (data) | ||
| 614 | free(data); | ||
| 615 | afc_unlock(client); | ||
| 616 | return ret; | ||
| 617 | } | ||
| 618 | /* Parse the data */ | ||
| 619 | *device_information = make_dictionary(data, bytes); | ||
| 620 | free(data); | ||
| 621 | |||
| 622 | afc_unlock(client); | ||
| 623 | |||
| 624 | return ret; | ||
| 625 | } | ||
| 626 | |||
| 498 | afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value) | 627 | afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value) |
| 499 | { | 628 | { |
| 500 | afc_error_t ret = AFC_E_INTERNAL_ERROR; | 629 | afc_error_t ret = AFC_E_INTERNAL_ERROR; |
| @@ -644,8 +773,6 @@ afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***fil | |||
| 644 | return AFC_E_NO_MEM; | 773 | return AFC_E_NO_MEM; |
| 645 | } | 774 | } |
| 646 | 775 | ||
| 647 | debug_info("We got %p and %p", client->afc_packet, AFC_PACKET_DATA_PTR); | ||
| 648 | |||
| 649 | /* Send command */ | 776 | /* Send command */ |
| 650 | memcpy(AFC_PACKET_DATA_PTR, path, data_len); | 777 | memcpy(AFC_PACKET_DATA_PTR, path, data_len); |
| 651 | ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes); | 778 | ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes); |
| @@ -666,6 +793,44 @@ afc_error_t afc_get_file_info(afc_client_t client, const char *path, char ***fil | |||
| 666 | return ret; | 793 | return ret; |
| 667 | } | 794 | } |
| 668 | 795 | ||
| 796 | afc_error_t afc_get_file_info_plist(afc_client_t client, const char *path, plist_t *file_information) | ||
| 797 | { | ||
| 798 | char *received = NULL; | ||
| 799 | uint32_t bytes = 0; | ||
| 800 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | ||
| 801 | |||
| 802 | if (!client || !path || !file_information) | ||
| 803 | return AFC_E_INVALID_ARG; | ||
| 804 | |||
| 805 | afc_lock(client); | ||
| 806 | |||
| 807 | uint32_t data_len = (uint32_t)strlen(path)+1; | ||
| 808 | if (_afc_check_packet_buffer(client, data_len) < 0) { | ||
| 809 | afc_unlock(client); | ||
| 810 | debug_info("Failed to realloc packet buffer"); | ||
| 811 | return AFC_E_NO_MEM; | ||
| 812 | } | ||
| 813 | |||
| 814 | /* Send command */ | ||
| 815 | memcpy(AFC_PACKET_DATA_PTR, path, data_len); | ||
| 816 | ret = afc_dispatch_packet(client, AFC_OP_GET_FILE_INFO, data_len, NULL, 0, &bytes); | ||
| 817 | if (ret != AFC_E_SUCCESS) { | ||
| 818 | afc_unlock(client); | ||
| 819 | return AFC_E_NOT_ENOUGH_DATA; | ||
| 820 | } | ||
| 821 | |||
| 822 | /* Receive data */ | ||
| 823 | ret = afc_receive_data(client, &received, &bytes); | ||
| 824 | if (received) { | ||
| 825 | *file_information = make_dictionary(received, bytes); | ||
| 826 | free(received); | ||
| 827 | } | ||
| 828 | |||
| 829 | afc_unlock(client); | ||
| 830 | |||
| 831 | return ret; | ||
| 832 | } | ||
| 833 | |||
| 669 | afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle) | 834 | afc_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle) |
| 670 | { | 835 | { |
| 671 | if (!client || !client->parent || !client->afc_packet) | 836 | if (!client || !client->parent || !client->afc_packet) |
| @@ -1182,14 +1347,14 @@ const char* afc_strerror(afc_error_t err) | |||
| 1182 | return "Internal error"; | 1347 | return "Internal error"; |
| 1183 | case AFC_E_MUX_ERROR: | 1348 | case AFC_E_MUX_ERROR: |
| 1184 | return "MUX error"; | 1349 | return "MUX error"; |
| 1350 | case AFC_E_SSL_ERROR: | ||
| 1351 | return "SSL error"; | ||
| 1185 | case AFC_E_NO_MEM: | 1352 | case AFC_E_NO_MEM: |
| 1186 | return "Out of memory"; | 1353 | return "Out of memory"; |
| 1187 | case AFC_E_NOT_ENOUGH_DATA: | 1354 | case AFC_E_NOT_ENOUGH_DATA: |
| 1188 | return "Not enough data"; | 1355 | return "Not enough data"; |
| 1189 | case AFC_E_DIR_NOT_EMPTY: | 1356 | case AFC_E_DIR_NOT_EMPTY: |
| 1190 | return "Directory not empty"; | 1357 | return "Directory not empty"; |
| 1191 | case AFC_E_FORCE_SIGNED_TYPE: | ||
| 1192 | return "Force signed type"; | ||
| 1193 | default: | 1358 | default: |
| 1194 | break; | 1359 | break; |
| 1195 | } | 1360 | } |
diff --git a/src/house_arrest.c b/src/house_arrest.c index caad731..06068c6 100644 --- a/src/house_arrest.c +++ b/src/house_arrest.c | |||
| @@ -24,7 +24,11 @@ | |||
| 24 | #endif | 24 | #endif |
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | |||
| 28 | #ifndef _MSC_VER | ||
| 27 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | #endif | ||
| 31 | |||
| 28 | #include <plist/plist.h> | 32 | #include <plist/plist.h> |
| 29 | 33 | ||
| 30 | #include "house_arrest.h" | 34 | #include "house_arrest.h" |
diff --git a/src/idevice.c b/src/idevice.c index b9bbb1f..0af27fd 100644 --- a/src/idevice.c +++ b/src/idevice.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <errno.h> | 30 | #include <errno.h> |
| 31 | #include <time.h> | 31 | #include <time.h> |
| 32 | 32 | ||
| 33 | #ifdef WIN32 | 33 | #ifdef _WIN32 |
| 34 | #include <winsock2.h> | 34 | #include <winsock2.h> |
| 35 | #include <ws2tcpip.h> | 35 | #include <ws2tcpip.h> |
| 36 | #include <windows.h> | 36 | #include <windows.h> |
| @@ -124,32 +124,32 @@ static void id_function(CRYPTO_THREADID *thread) | |||
| 124 | #endif | 124 | #endif |
| 125 | #endif /* HAVE_OPENSSL */ | 125 | #endif /* HAVE_OPENSSL */ |
| 126 | 126 | ||
| 127 | static void internal_idevice_init(void) | 127 | // Reference: https://stackoverflow.com/a/2390626/1806760 |
| 128 | { | 128 | // Initializer/finalizer sample for MSVC and GCC/Clang. |
| 129 | #if defined(HAVE_OPENSSL) | 129 | // 2010-2016 Joe Lowe. Released into the public domain. |
| 130 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) | 130 | |
| 131 | int i; | 131 | #ifdef __cplusplus |
| 132 | SSL_library_init(); | 132 | #define INITIALIZER(f) \ |
| 133 | 133 | static void f(void); \ | |
| 134 | mutex_buf = malloc(CRYPTO_num_locks() * sizeof(mutex_t)); | 134 | struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \ |
| 135 | if (!mutex_buf) | 135 | static void f(void) |
| 136 | return; | 136 | #elif defined(_MSC_VER) |
| 137 | for (i = 0; i < CRYPTO_num_locks(); i++) | 137 | #pragma section(".CRT$XCU",read) |
| 138 | mutex_init(&mutex_buf[i]); | 138 | #define INITIALIZER2_(f,p) \ |
| 139 | 139 | static void f(void); \ | |
| 140 | #if OPENSSL_VERSION_NUMBER < 0x10000000L | 140 | __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ |
| 141 | CRYPTO_set_id_callback(id_function); | 141 | __pragma(comment(linker,"/include:" p #f "_")) \ |
| 142 | static void f(void) | ||
| 143 | #ifdef _WIN64 | ||
| 144 | #define INITIALIZER(f) INITIALIZER2_(f,"") | ||
| 145 | #else | ||
| 146 | #define INITIALIZER(f) INITIALIZER2_(f,"_") | ||
| 147 | #endif | ||
| 142 | #else | 148 | #else |
| 143 | CRYPTO_THREADID_set_callback(id_function); | 149 | #define INITIALIZER(f) \ |
| 144 | #endif | 150 | static void f(void) __attribute__((__constructor__)); \ |
| 145 | CRYPTO_set_locking_callback(locking_function); | 151 | static void f(void) |
| 146 | #endif | ||
| 147 | #elif defined(HAVE_GNUTLS) | ||
| 148 | gnutls_global_init(); | ||
| 149 | #elif defined(HAVE_MBEDTLS) | ||
| 150 | // NO-OP | ||
| 151 | #endif | 152 | #endif |
| 152 | } | ||
| 153 | 153 | ||
| 154 | static void internal_idevice_deinit(void) | 154 | static void internal_idevice_deinit(void) |
| 155 | { | 155 | { |
| @@ -181,43 +181,33 @@ static void internal_idevice_deinit(void) | |||
| 181 | #endif | 181 | #endif |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static thread_once_t init_once = THREAD_ONCE_INIT; | 184 | INITIALIZER(internal_idevice_init) |
| 185 | static thread_once_t deinit_once = THREAD_ONCE_INIT; | ||
| 186 | |||
| 187 | #ifndef HAVE_ATTRIBUTE_CONSTRUCTOR | ||
| 188 | #if defined(__llvm__) || defined(__GNUC__) | ||
| 189 | #define HAVE_ATTRIBUTE_CONSTRUCTOR | ||
| 190 | #endif | ||
| 191 | #endif | ||
| 192 | |||
| 193 | #ifdef HAVE_ATTRIBUTE_CONSTRUCTOR | ||
| 194 | static void __attribute__((constructor)) libimobiledevice_initialize(void) | ||
| 195 | { | 185 | { |
| 196 | thread_once(&init_once, internal_idevice_init); | 186 | #if defined(HAVE_OPENSSL) |
| 197 | } | 187 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) |
| 188 | int i; | ||
| 189 | SSL_library_init(); | ||
| 198 | 190 | ||
| 199 | static void __attribute__((destructor)) libimobiledevice_deinitialize(void) | 191 | mutex_buf = malloc(CRYPTO_num_locks() * sizeof(mutex_t)); |
| 200 | { | 192 | if (!mutex_buf) |
| 201 | thread_once(&deinit_once, internal_idevice_deinit); | 193 | return; |
| 202 | } | 194 | for (i = 0; i < CRYPTO_num_locks(); i++) |
| 203 | #elif defined(WIN32) | 195 | mutex_init(&mutex_buf[i]); |
| 204 | BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) | 196 | |
| 205 | { | 197 | #if OPENSSL_VERSION_NUMBER < 0x10000000L |
| 206 | switch (dwReason) { | 198 | CRYPTO_set_id_callback(id_function); |
| 207 | case DLL_PROCESS_ATTACH: | ||
| 208 | thread_once(&init_once, internal_idevice_init); | ||
| 209 | break; | ||
| 210 | case DLL_PROCESS_DETACH: | ||
| 211 | thread_once(&deinit_once, internal_idevice_deinit); | ||
| 212 | break; | ||
| 213 | default: | ||
| 214 | break; | ||
| 215 | } | ||
| 216 | return 1; | ||
| 217 | } | ||
| 218 | #else | 199 | #else |
| 219 | #warning No compiler support for constructor/destructor attributes, some features might not be available. | 200 | CRYPTO_THREADID_set_callback(id_function); |
| 201 | #endif | ||
| 202 | CRYPTO_set_locking_callback(locking_function); | ||
| 203 | #endif | ||
| 204 | #elif defined(HAVE_GNUTLS) | ||
| 205 | gnutls_global_init(); | ||
| 206 | #elif defined(HAVE_MBEDTLS) | ||
| 207 | // NO-OP | ||
| 220 | #endif | 208 | #endif |
| 209 | atexit(internal_idevice_deinit); | ||
| 210 | } | ||
| 221 | 211 | ||
| 222 | const char* libimobiledevice_version() | 212 | const char* libimobiledevice_version() |
| 223 | { | 213 | { |
| @@ -548,7 +538,7 @@ idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connect | |||
| 548 | } | 538 | } |
| 549 | idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private)); | 539 | idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private)); |
| 550 | new_connection->type = CONNECTION_USBMUXD; | 540 | new_connection->type = CONNECTION_USBMUXD; |
| 551 | new_connection->data = (void*)(long)sfd; | 541 | new_connection->data = (void*)(uintptr_t)sfd; |
| 552 | new_connection->ssl_data = NULL; | 542 | new_connection->ssl_data = NULL; |
| 553 | new_connection->device = device; | 543 | new_connection->device = device; |
| 554 | new_connection->ssl_recv_timeout = (unsigned int)-1; | 544 | new_connection->ssl_recv_timeout = (unsigned int)-1; |
| @@ -593,7 +583,7 @@ idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connect | |||
| 593 | 583 | ||
| 594 | idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private)); | 584 | idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private)); |
| 595 | new_connection->type = CONNECTION_NETWORK; | 585 | new_connection->type = CONNECTION_NETWORK; |
| 596 | new_connection->data = (void*)(long)sfd; | 586 | new_connection->data = (void*)(uintptr_t)sfd; |
| 597 | new_connection->ssl_data = NULL; | 587 | new_connection->ssl_data = NULL; |
| 598 | new_connection->device = device; | 588 | new_connection->device = device; |
| 599 | new_connection->ssl_recv_timeout = (unsigned int)-1; | 589 | new_connection->ssl_recv_timeout = (unsigned int)-1; |
| @@ -618,11 +608,11 @@ idevice_error_t idevice_disconnect(idevice_connection_t connection) | |||
| 618 | } | 608 | } |
| 619 | idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; | 609 | idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; |
| 620 | if (connection->type == CONNECTION_USBMUXD) { | 610 | if (connection->type == CONNECTION_USBMUXD) { |
| 621 | usbmuxd_disconnect((int)(long)connection->data); | 611 | usbmuxd_disconnect((int)(uintptr_t)connection->data); |
| 622 | connection->data = NULL; | 612 | connection->data = NULL; |
| 623 | result = IDEVICE_E_SUCCESS; | 613 | result = IDEVICE_E_SUCCESS; |
| 624 | } else if (connection->type == CONNECTION_NETWORK) { | 614 | } else if (connection->type == CONNECTION_NETWORK) { |
| 625 | socket_close((int)(long)connection->data); | 615 | socket_close((int)(uintptr_t)connection->data); |
| 626 | connection->data = NULL; | 616 | connection->data = NULL; |
| 627 | result = IDEVICE_E_SUCCESS; | 617 | result = IDEVICE_E_SUCCESS; |
| 628 | } else { | 618 | } else { |
| @@ -647,7 +637,7 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection, | |||
| 647 | if (connection->type == CONNECTION_USBMUXD) { | 637 | if (connection->type == CONNECTION_USBMUXD) { |
| 648 | int res; | 638 | int res; |
| 649 | do { | 639 | do { |
| 650 | res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes); | 640 | res = usbmuxd_send((int)(uintptr_t)connection->data, data, len, sent_bytes); |
| 651 | } while (res == -EAGAIN); | 641 | } while (res == -EAGAIN); |
| 652 | if (res < 0) { | 642 | if (res < 0) { |
| 653 | debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res)); | 643 | debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res)); |
| @@ -656,7 +646,7 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection, | |||
| 656 | return IDEVICE_E_SUCCESS; | 646 | return IDEVICE_E_SUCCESS; |
| 657 | } | 647 | } |
| 658 | if (connection->type == CONNECTION_NETWORK) { | 648 | if (connection->type == CONNECTION_NETWORK) { |
| 659 | int s = socket_send((int)(long)connection->data, (void*)data, len); | 649 | int s = socket_send((int)(uintptr_t)connection->data, (void*)data, len); |
| 660 | if (s < 0) { | 650 | if (s < 0) { |
| 661 | *sent_bytes = 0; | 651 | *sent_bytes = 0; |
| 662 | return IDEVICE_E_UNKNOWN_ERROR; | 652 | return IDEVICE_E_UNKNOWN_ERROR; |
| @@ -763,7 +753,7 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t | |||
| 763 | } | 753 | } |
| 764 | 754 | ||
| 765 | if (connection->type == CONNECTION_USBMUXD) { | 755 | if (connection->type == CONNECTION_USBMUXD) { |
| 766 | int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); | 756 | int conn_error = usbmuxd_recv_timeout((int)(uintptr_t)connection->data, data, len, recv_bytes, timeout); |
| 767 | idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); | 757 | idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); |
| 768 | if (error == IDEVICE_E_UNKNOWN_ERROR) { | 758 | if (error == IDEVICE_E_UNKNOWN_ERROR) { |
| 769 | debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error)); | 759 | debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error)); |
| @@ -771,7 +761,7 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t | |||
| 771 | return error; | 761 | return error; |
| 772 | } | 762 | } |
| 773 | if (connection->type == CONNECTION_NETWORK) { | 763 | if (connection->type == CONNECTION_NETWORK) { |
| 774 | int res = socket_receive_timeout((int)(long)connection->data, data, len, 0, timeout); | 764 | int res = socket_receive_timeout((int)(uintptr_t)connection->data, data, len, 0, timeout); |
| 775 | idevice_error_t error = socket_recv_to_idevice_error(res, 0, 0); | 765 | idevice_error_t error = socket_recv_to_idevice_error(res, 0, 0); |
| 776 | if (error == IDEVICE_E_SUCCESS) { | 766 | if (error == IDEVICE_E_SUCCESS) { |
| 777 | *recv_bytes = (uint32_t)res; | 767 | *recv_bytes = (uint32_t)res; |
| @@ -863,7 +853,7 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti | |||
| 863 | } | 853 | } |
| 864 | 854 | ||
| 865 | if (connection->type == CONNECTION_USBMUXD) { | 855 | if (connection->type == CONNECTION_USBMUXD) { |
| 866 | int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes); | 856 | int res = usbmuxd_recv((int)(uintptr_t)connection->data, data, len, recv_bytes); |
| 867 | if (res < 0) { | 857 | if (res < 0) { |
| 868 | debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res)); | 858 | debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res)); |
| 869 | return IDEVICE_E_UNKNOWN_ERROR; | 859 | return IDEVICE_E_UNKNOWN_ERROR; |
| @@ -871,7 +861,7 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti | |||
| 871 | return IDEVICE_E_SUCCESS; | 861 | return IDEVICE_E_SUCCESS; |
| 872 | } | 862 | } |
| 873 | if (connection->type == CONNECTION_NETWORK) { | 863 | if (connection->type == CONNECTION_NETWORK) { |
| 874 | int res = socket_receive((int)(long)connection->data, data, len); | 864 | int res = socket_receive((int)(uintptr_t)connection->data, data, len); |
| 875 | if (res < 0) { | 865 | if (res < 0) { |
| 876 | debug_info("ERROR: socket_receive returned %d (%s)", res, strerror(-res)); | 866 | debug_info("ERROR: socket_receive returned %d (%s)", res, strerror(-res)); |
| 877 | return IDEVICE_E_UNKNOWN_ERROR; | 867 | return IDEVICE_E_UNKNOWN_ERROR; |
| @@ -924,11 +914,11 @@ idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int * | |||
| 924 | } | 914 | } |
| 925 | 915 | ||
| 926 | if (connection->type == CONNECTION_USBMUXD) { | 916 | if (connection->type == CONNECTION_USBMUXD) { |
| 927 | *fd = (int)(long)connection->data; | 917 | *fd = (int)(uintptr_t)connection->data; |
| 928 | return IDEVICE_E_SUCCESS; | 918 | return IDEVICE_E_SUCCESS; |
| 929 | } | 919 | } |
| 930 | if (connection->type == CONNECTION_NETWORK) { | 920 | if (connection->type == CONNECTION_NETWORK) { |
| 931 | *fd = (int)(long)connection->data; | 921 | *fd = (int)(uintptr_t)connection->data; |
| 932 | return IDEVICE_E_SUCCESS; | 922 | return IDEVICE_E_SUCCESS; |
| 933 | } | 923 | } |
| 934 | 924 | ||
| @@ -956,6 +946,20 @@ idevice_error_t idevice_get_udid(idevice_t device, char **udid) | |||
| 956 | return IDEVICE_E_SUCCESS; | 946 | return IDEVICE_E_SUCCESS; |
| 957 | } | 947 | } |
| 958 | 948 | ||
| 949 | unsigned int idevice_get_device_version(idevice_t device) | ||
| 950 | { | ||
| 951 | if (!device) { | ||
| 952 | return 0; | ||
| 953 | } | ||
| 954 | if (!device->version) { | ||
| 955 | lockdownd_client_t lockdown = NULL; | ||
| 956 | lockdownd_client_new(device, &lockdown, NULL); | ||
| 957 | // we don't handle any errors here. We should have the product version cached now. | ||
| 958 | lockdownd_client_free(lockdown); | ||
| 959 | } | ||
| 960 | return device->version; | ||
| 961 | } | ||
| 962 | |||
| 959 | #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) | 963 | #if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) |
| 960 | typedef ssize_t ssl_cb_ret_type_t; | 964 | typedef ssize_t ssl_cb_ret_type_t; |
| 961 | #elif defined(HAVE_MBEDTLS) | 965 | #elif defined(HAVE_MBEDTLS) |
| @@ -1075,13 +1079,14 @@ static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int arg | |||
| 1075 | idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b); | 1079 | idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b); |
| 1076 | #if OPENSSL_VERSION_NUMBER < 0x30000000L | 1080 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
| 1077 | size_t len = (size_t)argi; | 1081 | size_t len = (size_t)argi; |
| 1078 | size_t *processed = (size_t*)&bytes; | ||
| 1079 | #endif | 1082 | #endif |
| 1080 | switch (oper) { | 1083 | switch (oper) { |
| 1081 | case (BIO_CB_READ|BIO_CB_RETURN): | 1084 | case (BIO_CB_READ|BIO_CB_RETURN): |
| 1082 | if (argp) { | 1085 | if (argp) { |
| 1083 | bytes = internal_ssl_read(conn, (char *)argp, len); | 1086 | bytes = internal_ssl_read(conn, (char *)argp, len); |
| 1084 | *processed = bytes; | 1087 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
| 1088 | *processed = (size_t)(bytes < 0) ? 0 : bytes; | ||
| 1089 | #endif | ||
| 1085 | return (long)bytes; | 1090 | return (long)bytes; |
| 1086 | } | 1091 | } |
| 1087 | return 0; | 1092 | return 0; |
| @@ -1090,7 +1095,9 @@ static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int arg | |||
| 1090 | // fallthrough | 1095 | // fallthrough |
| 1091 | case (BIO_CB_WRITE|BIO_CB_RETURN): | 1096 | case (BIO_CB_WRITE|BIO_CB_RETURN): |
| 1092 | bytes = internal_ssl_write(conn, argp, len); | 1097 | bytes = internal_ssl_write(conn, argp, len); |
| 1093 | *processed = bytes; | 1098 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
| 1099 | *processed = (size_t)(bytes < 0) ? 0 : bytes; | ||
| 1100 | #endif | ||
| 1094 | return (long)bytes; | 1101 | return (long)bytes; |
| 1095 | default: | 1102 | default: |
| 1096 | return retvalue; | 1103 | return retvalue; |
| @@ -1239,7 +1246,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 1239 | #if OPENSSL_VERSION_NUMBER < 0x10100002L || \ | 1246 | #if OPENSSL_VERSION_NUMBER < 0x10100002L || \ |
| 1240 | (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2060000fL)) | 1247 | (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2060000fL)) |
| 1241 | /* force use of TLSv1 for older devices */ | 1248 | /* force use of TLSv1 for older devices */ |
| 1242 | if (connection->device->version < DEVICE_VERSION(10,0,0)) { | 1249 | if (connection->device->version < IDEVICE_DEVICE_VERSION(10,0,0)) { |
| 1243 | #ifdef SSL_OP_NO_TLSv1_1 | 1250 | #ifdef SSL_OP_NO_TLSv1_1 |
| 1244 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); | 1251 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); |
| 1245 | #endif | 1252 | #endif |
| @@ -1252,7 +1259,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 1252 | } | 1259 | } |
| 1253 | #else | 1260 | #else |
| 1254 | SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); | 1261 | SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); |
| 1255 | if (connection->device->version < DEVICE_VERSION(10,0,0)) { | 1262 | if (connection->device->version < IDEVICE_DEVICE_VERSION(10,0,0)) { |
| 1256 | SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION); | 1263 | SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION); |
| 1257 | if (connection->device->version == 0) { | 1264 | if (connection->device->version == 0) { |
| 1258 | /* | 1265 | /* |
| @@ -1338,7 +1345,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 1338 | if (ssl_error == 0 || ssl_error != SSL_ERROR_WANT_READ) { | 1345 | if (ssl_error == 0 || ssl_error != SSL_ERROR_WANT_READ) { |
| 1339 | break; | 1346 | break; |
| 1340 | } | 1347 | } |
| 1341 | #ifdef WIN32 | 1348 | #ifdef _WIN32 |
| 1342 | Sleep(100); | 1349 | Sleep(100); |
| 1343 | #else | 1350 | #else |
| 1344 | struct timespec ts = { 0, 100000000 }; | 1351 | struct timespec ts = { 0, 100000000 }; |
| @@ -1544,3 +1551,28 @@ idevice_error_t idevice_connection_disable_bypass_ssl(idevice_connection_t conne | |||
| 1544 | 1551 | ||
| 1545 | return IDEVICE_E_SUCCESS; | 1552 | return IDEVICE_E_SUCCESS; |
| 1546 | } | 1553 | } |
| 1554 | |||
| 1555 | const char* idevice_strerror(idevice_error_t err) | ||
| 1556 | { | ||
| 1557 | switch (err) { | ||
| 1558 | case IDEVICE_E_SUCCESS: | ||
| 1559 | return "Success"; | ||
| 1560 | case IDEVICE_E_INVALID_ARG: | ||
| 1561 | return "Invalid argument"; | ||
| 1562 | case IDEVICE_E_UNKNOWN_ERROR: | ||
| 1563 | return "Unknown Error"; | ||
| 1564 | case IDEVICE_E_NO_DEVICE: | ||
| 1565 | return "No device"; | ||
| 1566 | case IDEVICE_E_NOT_ENOUGH_DATA: | ||
| 1567 | return "Not enough data"; | ||
| 1568 | case IDEVICE_E_CONNREFUSED: | ||
| 1569 | return "Connection refused"; | ||
| 1570 | case IDEVICE_E_SSL_ERROR: | ||
| 1571 | return "SSL error"; | ||
| 1572 | case IDEVICE_E_TIMEOUT: | ||
| 1573 | return "Timeout"; | ||
| 1574 | default: | ||
| 1575 | break; | ||
| 1576 | } | ||
| 1577 | return "Unknown Error"; | ||
| 1578 | } | ||
diff --git a/src/idevice.h b/src/idevice.h index dd72f9d..e05338e 100644 --- a/src/idevice.h +++ b/src/idevice.h | |||
| @@ -52,8 +52,6 @@ | |||
| 52 | #include "common/userpref.h" | 52 | #include "common/userpref.h" |
| 53 | #include "libimobiledevice/libimobiledevice.h" | 53 | #include "libimobiledevice/libimobiledevice.h" |
| 54 | 54 | ||
| 55 | #define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF)) | ||
| 56 | |||
| 57 | #define DEVICE_CLASS_IPHONE 1 | 55 | #define DEVICE_CLASS_IPHONE 1 |
| 58 | #define DEVICE_CLASS_IPAD 2 | 56 | #define DEVICE_CLASS_IPAD 2 |
| 59 | #define DEVICE_CLASS_IPOD 3 | 57 | #define DEVICE_CLASS_IPOD 3 |
diff --git a/src/installation_proxy.c b/src/installation_proxy.c index ec19da0..bb6ef01 100644 --- a/src/installation_proxy.c +++ b/src/installation_proxy.c | |||
| @@ -26,7 +26,11 @@ | |||
| 26 | #include <string.h> | 26 | #include <string.h> |
| 27 | #include <stdlib.h> | 27 | #include <stdlib.h> |
| 28 | #include <inttypes.h> | 28 | #include <inttypes.h> |
| 29 | |||
| 30 | #ifndef _MSC_VER | ||
| 29 | #include <unistd.h> | 31 | #include <unistd.h> |
| 32 | #endif | ||
| 33 | |||
| 30 | #include <plist/plist.h> | 34 | #include <plist/plist.h> |
| 31 | 35 | ||
| 32 | #include "installation_proxy.h" | 36 | #include "installation_proxy.h" |
| @@ -251,7 +255,7 @@ instproxy_error_t instproxy_client_new(idevice_t device, lockdownd_service_descr | |||
| 251 | 255 | ||
| 252 | instproxy_error_t instproxy_client_start_service(idevice_t device, instproxy_client_t * client, const char* label) | 256 | instproxy_error_t instproxy_client_start_service(idevice_t device, instproxy_client_t * client, const char* label) |
| 253 | { | 257 | { |
| 254 | instproxy_error_t err = INSTPROXY_E_UNKNOWN_ERROR; | 258 | int32_t err = INSTPROXY_E_UNKNOWN_ERROR; |
| 255 | service_client_factory_start_service(device, INSTPROXY_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(instproxy_client_new), &err); | 259 | service_client_factory_start_service(device, INSTPROXY_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(instproxy_client_new), &err); |
| 256 | return err; | 260 | return err; |
| 257 | } | 261 | } |
diff --git a/src/lockdown-cu.c b/src/lockdown-cu.c index 1afc2c5..c457cb2 100644 --- a/src/lockdown-cu.c +++ b/src/lockdown-cu.c | |||
| @@ -29,7 +29,11 @@ | |||
| 29 | #define __USE_GNU 1 | 29 | #define __USE_GNU 1 |
| 30 | #include <stdio.h> | 30 | #include <stdio.h> |
| 31 | #include <ctype.h> | 31 | #include <ctype.h> |
| 32 | |||
| 33 | #ifndef _MSC_VER | ||
| 32 | #include <unistd.h> | 34 | #include <unistd.h> |
| 35 | #endif | ||
| 36 | |||
| 33 | #include <plist/plist.h> | 37 | #include <plist/plist.h> |
| 34 | 38 | ||
| 35 | #include "idevice.h" | 39 | #include "idevice.h" |
| @@ -505,7 +509,7 @@ lockdownd_error_t lockdownd_cu_pairing_create(lockdownd_client_t client, lockdow | |||
| 505 | char *s_version = NULL; | 509 | char *s_version = NULL; |
| 506 | plist_get_string_val(p_version, &s_version); | 510 | plist_get_string_val(p_version, &s_version); |
| 507 | if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { | 511 | if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { |
| 508 | client->device->version = DEVICE_VERSION(vers[0], vers[1], vers[2]); | 512 | client->device->version = IDEVICE_DEVICE_VERSION(vers[0], vers[1], vers[2]); |
| 509 | } | 513 | } |
| 510 | free(s_version); | 514 | free(s_version); |
| 511 | } | 515 | } |
| @@ -653,7 +657,7 @@ lockdownd_error_t lockdownd_cu_pairing_create(lockdownd_client_t client, lockdow | |||
| 653 | CFStringGetCString(cname, hostname, sizeof(hostname), kCFStringEncodingUTF8); | 657 | CFStringGetCString(cname, hostname, sizeof(hostname), kCFStringEncodingUTF8); |
| 654 | CFRelease(cname); | 658 | CFRelease(cname); |
| 655 | #else | 659 | #else |
| 656 | #ifdef WIN32 | 660 | #ifdef _WIN32 |
| 657 | DWORD hostname_len = sizeof(hostname); | 661 | DWORD hostname_len = sizeof(hostname); |
| 658 | GetComputerName(hostname, &hostname_len); | 662 | GetComputerName(hostname, &hostname_len); |
| 659 | #else | 663 | #else |
| @@ -957,12 +961,12 @@ lockdownd_error_t lockdownd_cu_send_request_and_get_reply(lockdownd_client_t cli | |||
| 957 | hkdf_md(MD_ALGO_SHA512, (unsigned char*)READ_KEY_SALT_MDLD, sizeof(READ_KEY_SALT_MDLD)-1, (unsigned char*)READ_KEY_INFO_MDLD, sizeof(READ_KEY_INFO_MDLD)-1, client->cu_key, client->cu_key_len, cu_read_key, &cu_read_key_len); | 961 | hkdf_md(MD_ALGO_SHA512, (unsigned char*)READ_KEY_SALT_MDLD, sizeof(READ_KEY_SALT_MDLD)-1, (unsigned char*)READ_KEY_INFO_MDLD, sizeof(READ_KEY_INFO_MDLD)-1, client->cu_key, client->cu_key_len, cu_read_key, &cu_read_key_len); |
| 958 | 962 | ||
| 959 | // Starting with iOS/tvOS 11.2 and WatchOS 4.2, this nonce is random and sent along with the request. Before, the request doesn't have a nonce and it uses hardcoded nonce "sendone01234". | 963 | // Starting with iOS/tvOS 11.2 and WatchOS 4.2, this nonce is random and sent along with the request. Before, the request doesn't have a nonce and it uses hardcoded nonce "sendone01234". |
| 960 | unsigned char cu_nonce[12] = "sendone01234"; // guaranteed to be random by fair dice troll | 964 | unsigned char cu_nonce[] = "sendone01234"; // guaranteed to be random by fair dice troll |
| 961 | if (client->device->version >= DEVICE_VERSION(11,2,0)) { | 965 | if (client->device->version >= IDEVICE_DEVICE_VERSION(11,2,0)) { |
| 962 | #if defined(HAVE_OPENSSL) | 966 | #if defined(HAVE_OPENSSL) |
| 963 | RAND_bytes(cu_nonce, sizeof(cu_nonce)); | 967 | RAND_bytes(cu_nonce, sizeof(cu_nonce)-1); |
| 964 | #elif defined(HAVE_GCRYPT) | 968 | #elif defined(HAVE_GCRYPT) |
| 965 | gcry_create_nonce(cu_nonce, sizeof(cu_nonce)); | 969 | gcry_create_nonce(cu_nonce, sizeof(cu_nonce)-1); |
| 966 | #endif | 970 | #endif |
| 967 | } | 971 | } |
| 968 | 972 | ||
| @@ -1128,7 +1132,7 @@ lockdownd_error_t lockdownd_pair_cu(lockdownd_client_t client) | |||
| 1128 | plist_free(pubkey); | 1132 | plist_free(pubkey); |
| 1129 | 1133 | ||
| 1130 | plist_t pair_record_plist = plist_new_dict(); | 1134 | plist_t pair_record_plist = plist_new_dict(); |
| 1131 | pair_record_generate_keys_and_certs(pair_record_plist, public_key); | 1135 | pair_record_generate_keys_and_certs(pair_record_plist, public_key, client->device->version); |
| 1132 | 1136 | ||
| 1133 | char* host_id = NULL; | 1137 | char* host_id = NULL; |
| 1134 | char* system_buid = NULL; | 1138 | char* system_buid = NULL; |
diff --git a/src/lockdown.c b/src/lockdown.c index 256bff0..32389c9 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -32,7 +32,11 @@ | |||
| 32 | #define __USE_GNU 1 | 32 | #define __USE_GNU 1 |
| 33 | #include <stdio.h> | 33 | #include <stdio.h> |
| 34 | #include <ctype.h> | 34 | #include <ctype.h> |
| 35 | |||
| 36 | #ifndef _MSC_VER | ||
| 35 | #include <unistd.h> | 37 | #include <unistd.h> |
| 38 | #endif | ||
| 39 | |||
| 36 | #include <plist/plist.h> | 40 | #include <plist/plist.h> |
| 37 | #include <libimobiledevice-glue/utils.h> | 41 | #include <libimobiledevice-glue/utils.h> |
| 38 | 42 | ||
| @@ -43,7 +47,7 @@ | |||
| 43 | #include "common/userpref.h" | 47 | #include "common/userpref.h" |
| 44 | #include "asprintf.h" | 48 | #include "asprintf.h" |
| 45 | 49 | ||
| 46 | #ifdef WIN32 | 50 | #ifdef _WIN32 |
| 47 | #include <windows.h> | 51 | #include <windows.h> |
| 48 | #define sleep(x) Sleep(x*1000) | 52 | #define sleep(x) Sleep(x*1000) |
| 49 | #endif | 53 | #endif |
| @@ -617,6 +621,7 @@ lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *cli | |||
| 617 | .port = 0xf27e, | 621 | .port = 0xf27e, |
| 618 | .ssl_enabled = 0 | 622 | .ssl_enabled = 0 |
| 619 | }; | 623 | }; |
| 624 | char *type = NULL; | ||
| 620 | 625 | ||
| 621 | property_list_service_client_t plistclient = NULL; | 626 | property_list_service_client_t plistclient = NULL; |
| 622 | if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { | 627 | if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { |
| @@ -638,51 +643,32 @@ lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *cli | |||
| 638 | 643 | ||
| 639 | client_loc->label = label ? strdup(label) : NULL; | 644 | client_loc->label = label ? strdup(label) : NULL; |
| 640 | 645 | ||
| 641 | *client = client_loc; | 646 | int is_lockdownd = 0; |
| 642 | 647 | if (lockdownd_query_type(client_loc, &type) != LOCKDOWN_E_SUCCESS) { | |
| 643 | return LOCKDOWN_E_SUCCESS; | ||
| 644 | } | ||
| 645 | |||
| 646 | lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, const char *label) | ||
| 647 | { | ||
| 648 | if (!client) | ||
| 649 | return LOCKDOWN_E_INVALID_ARG; | ||
| 650 | |||
| 651 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | ||
| 652 | lockdownd_client_t client_loc = NULL; | ||
| 653 | plist_t pair_record = NULL; | ||
| 654 | char *host_id = NULL; | ||
| 655 | char *type = NULL; | ||
| 656 | |||
| 657 | ret = lockdownd_client_new(device, &client_loc, label); | ||
| 658 | if (LOCKDOWN_E_SUCCESS != ret) { | ||
| 659 | debug_info("failed to create lockdownd client."); | ||
| 660 | return ret; | ||
| 661 | } | ||
| 662 | |||
| 663 | /* perform handshake */ | ||
| 664 | ret = lockdownd_query_type(client_loc, &type); | ||
| 665 | if (LOCKDOWN_E_SUCCESS != ret) { | ||
| 666 | debug_info("QueryType failed in the lockdownd client."); | 648 | debug_info("QueryType failed in the lockdownd client."); |
| 667 | } else if (strcmp("com.apple.mobile.lockdown", type) != 0) { | 649 | } else if (!strcmp("com.apple.mobile.lockdown", type)) { |
| 668 | debug_info("Warning QueryType request returned \"%s\".", type); | 650 | is_lockdownd = 1; |
| 651 | } else { | ||
| 652 | debug_info("QueryType request returned \"%s\"", type); | ||
| 669 | } | 653 | } |
| 670 | free(type); | 654 | free(type); |
| 671 | 655 | ||
| 672 | if (device->version == 0) { | 656 | *client = client_loc; |
| 657 | |||
| 658 | if (is_lockdownd && device->version == 0) { | ||
| 673 | plist_t p_version = NULL; | 659 | plist_t p_version = NULL; |
| 674 | if (lockdownd_get_value(client_loc, NULL, "ProductVersion", &p_version) == LOCKDOWN_E_SUCCESS) { | 660 | if (lockdownd_get_value(client_loc, NULL, "ProductVersion", &p_version) == LOCKDOWN_E_SUCCESS) { |
| 675 | int vers[3] = {0, 0, 0}; | 661 | int vers[3] = {0, 0, 0}; |
| 676 | char *s_version = NULL; | 662 | char *s_version = NULL; |
| 677 | plist_get_string_val(p_version, &s_version); | 663 | plist_get_string_val(p_version, &s_version); |
| 678 | if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { | 664 | if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { |
| 679 | device->version = DEVICE_VERSION(vers[0], vers[1], vers[2]); | 665 | device->version = IDEVICE_DEVICE_VERSION(vers[0], vers[1], vers[2]); |
| 680 | } | 666 | } |
| 681 | free(s_version); | 667 | free(s_version); |
| 682 | } | 668 | } |
| 683 | plist_free(p_version); | 669 | plist_free(p_version); |
| 684 | } | 670 | } |
| 685 | if (device->device_class == 0) { | 671 | if (is_lockdownd && device->device_class == 0) { |
| 686 | plist_t p_device_class = NULL; | 672 | plist_t p_device_class = NULL; |
| 687 | if (lockdownd_get_value(client_loc, NULL, "DeviceClass", &p_device_class) == LOCKDOWN_E_SUCCESS) { | 673 | if (lockdownd_get_value(client_loc, NULL, "DeviceClass", &p_device_class) == LOCKDOWN_E_SUCCESS) { |
| 688 | char* s_device_class = NULL; | 674 | char* s_device_class = NULL; |
| @@ -707,6 +693,26 @@ lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdown | |||
| 707 | plist_free(p_device_class); | 693 | plist_free(p_device_class); |
| 708 | } | 694 | } |
| 709 | 695 | ||
| 696 | return LOCKDOWN_E_SUCCESS; | ||
| 697 | } | ||
| 698 | |||
| 699 | lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, const char *label) | ||
| 700 | { | ||
| 701 | if (!client) | ||
| 702 | return LOCKDOWN_E_INVALID_ARG; | ||
| 703 | |||
| 704 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | ||
| 705 | lockdownd_client_t client_loc = NULL; | ||
| 706 | plist_t pair_record = NULL; | ||
| 707 | char *host_id = NULL; | ||
| 708 | |||
| 709 | ret = lockdownd_client_new(device, &client_loc, label); | ||
| 710 | if (LOCKDOWN_E_SUCCESS != ret) { | ||
| 711 | debug_info("failed to create lockdownd client."); | ||
| 712 | return ret; | ||
| 713 | } | ||
| 714 | |||
| 715 | /* perform handshake */ | ||
| 710 | userpref_error_t uerr = userpref_read_pair_record(client_loc->device->udid, &pair_record); | 716 | userpref_error_t uerr = userpref_read_pair_record(client_loc->device->udid, &pair_record); |
| 711 | if (uerr == USERPREF_E_READ_ERROR) { | 717 | if (uerr == USERPREF_E_READ_ERROR) { |
| 712 | debug_info("ERROR: Failed to retrieve pair record for %s", client_loc->device->udid); | 718 | debug_info("ERROR: Failed to retrieve pair record for %s", client_loc->device->udid); |
| @@ -730,7 +736,7 @@ lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdown | |||
| 730 | plist_free(pair_record); | 736 | plist_free(pair_record); |
| 731 | pair_record = NULL; | 737 | pair_record = NULL; |
| 732 | 738 | ||
| 733 | if (device->version < DEVICE_VERSION(7,0,0) && device->device_class != DEVICE_CLASS_WATCH) { | 739 | if (device->version < IDEVICE_DEVICE_VERSION(7,0,0) && device->device_class != DEVICE_CLASS_WATCH) { |
| 734 | /* for older devices, we need to validate pairing to receive trusted host status */ | 740 | /* for older devices, we need to validate pairing to receive trusted host status */ |
| 735 | ret = lockdownd_validate_pair(client_loc, NULL); | 741 | ret = lockdownd_validate_pair(client_loc, NULL); |
| 736 | 742 | ||
| @@ -836,7 +842,7 @@ static lockdownd_error_t pair_record_generate(lockdownd_client_t client, plist_t | |||
| 836 | 842 | ||
| 837 | /* generate keys and certificates into pair record */ | 843 | /* generate keys and certificates into pair record */ |
| 838 | userpref_error_t uret = USERPREF_E_SUCCESS; | 844 | userpref_error_t uret = USERPREF_E_SUCCESS; |
| 839 | uret = pair_record_generate_keys_and_certs(*pair_record, public_key); | 845 | uret = pair_record_generate_keys_and_certs(*pair_record, public_key, client->device->version); |
| 840 | switch(uret) { | 846 | switch(uret) { |
| 841 | case USERPREF_E_INVALID_ARG: | 847 | case USERPREF_E_INVALID_ARG: |
| 842 | ret = LOCKDOWN_E_INVALID_ARG; | 848 | ret = LOCKDOWN_E_INVALID_ARG; |
| @@ -846,6 +852,7 @@ static lockdownd_error_t pair_record_generate(lockdownd_client_t client, plist_t | |||
| 846 | break; | 852 | break; |
| 847 | case USERPREF_E_SSL_ERROR: | 853 | case USERPREF_E_SSL_ERROR: |
| 848 | ret = LOCKDOWN_E_SSL_ERROR; | 854 | ret = LOCKDOWN_E_SSL_ERROR; |
| 855 | break; | ||
| 849 | default: | 856 | default: |
| 850 | break; | 857 | break; |
| 851 | } | 858 | } |
diff --git a/src/misagent.c b/src/misagent.c index e3da997..3fdca4d 100644 --- a/src/misagent.c +++ b/src/misagent.c | |||
| @@ -24,9 +24,13 @@ | |||
| 24 | #endif | 24 | #endif |
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <stdio.h> | ||
| 28 | |||
| 29 | #ifndef _MSC_VER | ||
| 27 | #include <unistd.h> | 30 | #include <unistd.h> |
| 31 | #endif | ||
| 32 | |||
| 28 | #include <plist/plist.h> | 33 | #include <plist/plist.h> |
| 29 | #include <stdio.h> | ||
| 30 | 34 | ||
| 31 | #include "misagent.h" | 35 | #include "misagent.h" |
| 32 | #include "property_list_service.h" | 36 | #include "property_list_service.h" |
diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c index 6df50c4..6677882 100644 --- a/src/mobile_image_mounter.c +++ b/src/mobile_image_mounter.c | |||
| @@ -24,7 +24,11 @@ | |||
| 24 | #endif | 24 | #endif |
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | |||
| 28 | #ifndef _MSC_VER | ||
| 27 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | #endif | ||
| 31 | |||
| 28 | #include <plist/plist.h> | 32 | #include <plist/plist.h> |
| 29 | 33 | ||
| 30 | #include "mobile_image_mounter.h" | 34 | #include "mobile_image_mounter.h" |
diff --git a/src/notification_proxy.c b/src/notification_proxy.c index 60b2e03..c7e4660 100644 --- a/src/notification_proxy.c +++ b/src/notification_proxy.c | |||
| @@ -24,14 +24,19 @@ | |||
| 24 | #endif | 24 | #endif |
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | |||
| 28 | #ifndef _MSC_VER | ||
| 27 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | #endif | ||
| 31 | |||
| 28 | #include <plist/plist.h> | 32 | #include <plist/plist.h> |
| 29 | 33 | ||
| 30 | #include "notification_proxy.h" | 34 | #include "notification_proxy.h" |
| 31 | #include "property_list_service.h" | 35 | #include "property_list_service.h" |
| 32 | #include "common/debug.h" | 36 | #include "common/debug.h" |
| 33 | 37 | ||
| 34 | #ifdef WIN32 | 38 | #ifdef _WIN32 |
| 39 | #include <windows.h> | ||
| 35 | #define sleep(x) Sleep(x*1000) | 40 | #define sleep(x) Sleep(x*1000) |
| 36 | #endif | 41 | #endif |
| 37 | 42 | ||
| @@ -109,7 +114,7 @@ np_error_t np_client_new(idevice_t device, lockdownd_service_descriptor_t servic | |||
| 109 | 114 | ||
| 110 | np_error_t np_client_start_service(idevice_t device, np_client_t* client, const char* label) | 115 | np_error_t np_client_start_service(idevice_t device, np_client_t* client, const char* label) |
| 111 | { | 116 | { |
| 112 | np_error_t err = NP_E_UNKNOWN_ERROR; | 117 | int32_t err = NP_E_UNKNOWN_ERROR; |
| 113 | service_client_factory_start_service(device, NP_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(np_client_new), &err); | 118 | service_client_factory_start_service(device, NP_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(np_client_new), &err); |
| 114 | return err; | 119 | return err; |
| 115 | } | 120 | } |
diff --git a/src/ostrace.c b/src/ostrace.c new file mode 100644 index 0000000..68eb6bf --- /dev/null +++ b/src/ostrace.c | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | /* | ||
| 2 | * ostrace.c | ||
| 3 | * com.apple.os_trace_relay service implementation. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2020-2025 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifdef HAVE_CONFIG_H | ||
| 23 | #include <config.h> | ||
| 24 | #endif | ||
| 25 | #include <string.h> | ||
| 26 | #include <stdlib.h> | ||
| 27 | |||
| 28 | #include <plist/plist.h> | ||
| 29 | |||
| 30 | #include "ostrace.h" | ||
| 31 | #include "lockdown.h" | ||
| 32 | #include "common/debug.h" | ||
| 33 | #include "endianness.h" | ||
| 34 | |||
| 35 | struct ostrace_worker_thread { | ||
| 36 | ostrace_client_t client; | ||
| 37 | ostrace_activity_cb_t cbfunc; | ||
| 38 | void *user_data; | ||
| 39 | }; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Convert a service_error_t value to a ostrace_error_t value. | ||
| 43 | * Used internally to get correct error codes. | ||
| 44 | * | ||
| 45 | * @param err An service_error_t error code | ||
| 46 | * | ||
| 47 | * @return A matching ostrace_error_t error code, | ||
| 48 | * OSTRACE_E_UNKNOWN_ERROR otherwise. | ||
| 49 | */ | ||
| 50 | static ostrace_error_t ostrace_error(service_error_t err) | ||
| 51 | { | ||
| 52 | switch (err) { | ||
| 53 | case SERVICE_E_SUCCESS: | ||
| 54 | return OSTRACE_E_SUCCESS; | ||
| 55 | case SERVICE_E_INVALID_ARG: | ||
| 56 | return OSTRACE_E_INVALID_ARG; | ||
| 57 | case SERVICE_E_MUX_ERROR: | ||
| 58 | return OSTRACE_E_MUX_ERROR; | ||
| 59 | case SERVICE_E_SSL_ERROR: | ||
| 60 | return OSTRACE_E_SSL_ERROR; | ||
| 61 | case SERVICE_E_NOT_ENOUGH_DATA: | ||
| 62 | return OSTRACE_E_NOT_ENOUGH_DATA; | ||
| 63 | case SERVICE_E_TIMEOUT: | ||
| 64 | return OSTRACE_E_TIMEOUT; | ||
| 65 | default: | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | return OSTRACE_E_UNKNOWN_ERROR; | ||
| 69 | } | ||
| 70 | |||
| 71 | ostrace_error_t ostrace_client_new(idevice_t device, lockdownd_service_descriptor_t service, ostrace_client_t * client) | ||
| 72 | { | ||
| 73 | *client = NULL; | ||
| 74 | |||
| 75 | if (!device || !service || service->port == 0 || !client || *client) { | ||
| 76 | debug_info("Incorrect parameter passed to ostrace_client_new."); | ||
| 77 | return OSTRACE_E_INVALID_ARG; | ||
| 78 | } | ||
| 79 | |||
| 80 | debug_info("Creating ostrace_client, port = %d.", service->port); | ||
| 81 | |||
| 82 | service_client_t parent = NULL; | ||
| 83 | ostrace_error_t ret = ostrace_error(service_client_new(device, service, &parent)); | ||
| 84 | if (ret != OSTRACE_E_SUCCESS) { | ||
| 85 | debug_info("Creating base service client failed. Error: %i", ret); | ||
| 86 | return ret; | ||
| 87 | } | ||
| 88 | |||
| 89 | ostrace_client_t client_loc = (ostrace_client_t) malloc(sizeof(struct ostrace_client_private)); | ||
| 90 | client_loc->parent = parent; | ||
| 91 | client_loc->worker = THREAD_T_NULL; | ||
| 92 | |||
| 93 | *client = client_loc; | ||
| 94 | |||
| 95 | debug_info("ostrace_client successfully created."); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | ostrace_error_t ostrace_client_start_service(idevice_t device, ostrace_client_t * client, const char* label) | ||
| 100 | { | ||
| 101 | ostrace_error_t err = OSTRACE_E_UNKNOWN_ERROR; | ||
| 102 | service_client_factory_start_service(device, OSTRACE_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(ostrace_client_new), &err); | ||
| 103 | return err; | ||
| 104 | } | ||
| 105 | |||
| 106 | ostrace_error_t ostrace_client_free(ostrace_client_t client) | ||
| 107 | { | ||
| 108 | if (!client) | ||
| 109 | return OSTRACE_E_INVALID_ARG; | ||
| 110 | ostrace_stop_activity(client); | ||
| 111 | ostrace_error_t err = ostrace_error(service_client_free(client->parent)); | ||
| 112 | free(client); | ||
| 113 | |||
| 114 | return err; | ||
| 115 | } | ||
| 116 | |||
| 117 | static ostrace_error_t ostrace_send_plist(ostrace_client_t client, plist_t plist) | ||
| 118 | { | ||
| 119 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 120 | uint32_t blen = 0; | ||
| 121 | char* bin = NULL; | ||
| 122 | uint32_t sent = 0; | ||
| 123 | uint32_t swapped_len = 0; | ||
| 124 | |||
| 125 | if (!client || !plist) { | ||
| 126 | return OSTRACE_E_INVALID_ARG; | ||
| 127 | } | ||
| 128 | |||
| 129 | plist_to_bin(plist, &bin, &blen); | ||
| 130 | swapped_len = htobe32(blen); | ||
| 131 | |||
| 132 | res = ostrace_error(service_send(client->parent, (char*)&swapped_len, 4, &sent)); | ||
| 133 | if (res == OSTRACE_E_SUCCESS) { | ||
| 134 | res = ostrace_error(service_send(client->parent, bin, blen, &sent)); | ||
| 135 | } | ||
| 136 | free(bin); | ||
| 137 | return res; | ||
| 138 | } | ||
| 139 | |||
| 140 | static ostrace_error_t ostrace_receive_plist(ostrace_client_t client, plist_t *plist) | ||
| 141 | { | ||
| 142 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 143 | uint8_t msgtype = 0; | ||
| 144 | uint32_t received = 0; | ||
| 145 | res = ostrace_error(service_receive(client->parent, (char*)&msgtype, 1, &received)); | ||
| 146 | if (res != OSTRACE_E_SUCCESS) { | ||
| 147 | debug_info("Failed to read message type from service"); | ||
| 148 | return res; | ||
| 149 | } | ||
| 150 | uint32_t rlen = 0; | ||
| 151 | res = ostrace_error(service_receive(client->parent, (char*)&rlen, 4, &received)); | ||
| 152 | if (res != OSTRACE_E_SUCCESS) { | ||
| 153 | debug_info("Failed to read message size from service"); | ||
| 154 | return res; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (msgtype == 1) { | ||
| 158 | rlen = be32toh(rlen); | ||
| 159 | } else if (msgtype == 2) { | ||
| 160 | rlen = le32toh(rlen); | ||
| 161 | } else { | ||
| 162 | debug_info("Unexpected message type %d", msgtype); | ||
| 163 | return OSTRACE_E_UNKNOWN_ERROR; | ||
| 164 | } | ||
| 165 | debug_info("got length %d", rlen); | ||
| 166 | |||
| 167 | char* buf = (char*)malloc(rlen); | ||
| 168 | res = ostrace_error(service_receive(client->parent, buf, rlen, &received)); | ||
| 169 | if (res != OSTRACE_E_SUCCESS) { | ||
| 170 | return res; | ||
| 171 | } | ||
| 172 | |||
| 173 | plist_t reply = NULL; | ||
| 174 | plist_err_t perr = plist_from_memory(buf, received, &reply, NULL); | ||
| 175 | free(buf); | ||
| 176 | if (perr != PLIST_ERR_SUCCESS) { | ||
| 177 | return OSTRACE_E_UNKNOWN_ERROR; | ||
| 178 | } | ||
| 179 | *plist = reply; | ||
| 180 | return OSTRACE_E_SUCCESS; | ||
| 181 | } | ||
| 182 | |||
| 183 | static ostrace_error_t _ostrace_check_result(plist_t reply) | ||
| 184 | { | ||
| 185 | ostrace_error_t res = OSTRACE_E_REQUEST_FAILED; | ||
| 186 | if (!reply) { | ||
| 187 | return res; | ||
| 188 | } | ||
| 189 | plist_t p_status = plist_dict_get_item(reply, "Status"); | ||
| 190 | if (!p_status) { | ||
| 191 | return res; | ||
| 192 | } | ||
| 193 | const char* status = plist_get_string_ptr(p_status, NULL); | ||
| 194 | if (!status) { | ||
| 195 | return res; | ||
| 196 | } | ||
| 197 | if (!strcmp(status, "RequestSuccessful")) { | ||
| 198 | res = OSTRACE_E_SUCCESS; | ||
| 199 | } | ||
| 200 | return res; | ||
| 201 | } | ||
| 202 | |||
| 203 | void *ostrace_worker(void *arg) | ||
| 204 | { | ||
| 205 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 206 | struct ostrace_worker_thread *oswt = (struct ostrace_worker_thread*)arg; | ||
| 207 | |||
| 208 | if (!oswt) | ||
| 209 | return NULL; | ||
| 210 | |||
| 211 | uint8_t msgtype = 0; | ||
| 212 | uint32_t received = 0; | ||
| 213 | |||
| 214 | debug_info("Running"); | ||
| 215 | |||
| 216 | while (oswt->client->parent) { | ||
| 217 | res = ostrace_error(service_receive_with_timeout(oswt->client->parent, (char*)&msgtype, 1, &received, 100)); | ||
| 218 | if (res == OSTRACE_E_TIMEOUT) { | ||
| 219 | continue; | ||
| 220 | } | ||
| 221 | if (res != OSTRACE_E_SUCCESS) { | ||
| 222 | debug_info("Failed to read message type from service"); | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | uint32_t rlen = 0; | ||
| 226 | res = ostrace_error(service_receive(oswt->client->parent, (char*)&rlen, 4, &received)); | ||
| 227 | if (res != OSTRACE_E_SUCCESS) { | ||
| 228 | debug_info("Failed to read message size from service"); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | |||
| 232 | if (msgtype == 1) { | ||
| 233 | rlen = be32toh(rlen); | ||
| 234 | } else if (msgtype == 2) { | ||
| 235 | rlen = le32toh(rlen); | ||
| 236 | } else { | ||
| 237 | debug_info("Unexpected message type %d", msgtype); | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | |||
| 241 | debug_info("got length %d", rlen); | ||
| 242 | |||
| 243 | void* buf = malloc(rlen); | ||
| 244 | res = ostrace_error(service_receive(oswt->client->parent, (char*)buf, rlen, &received)); | ||
| 245 | if (res != OSTRACE_E_SUCCESS) { | ||
| 246 | debug_info("Failed to receive %d bytes, error %d", rlen, res); | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | if (received < rlen) { | ||
| 250 | debug_info("Failed to receive all data, got %d/%d", received, rlen); | ||
| 251 | break; | ||
| 252 | } | ||
| 253 | oswt->cbfunc(buf, received, oswt->user_data); | ||
| 254 | } | ||
| 255 | |||
| 256 | if (oswt) { | ||
| 257 | free(oswt); | ||
| 258 | } | ||
| 259 | |||
| 260 | debug_info("Exiting"); | ||
| 261 | |||
| 262 | return NULL; | ||
| 263 | } | ||
| 264 | |||
| 265 | ostrace_error_t ostrace_start_activity(ostrace_client_t client, plist_t options, ostrace_activity_cb_t callback, void* user_data) | ||
| 266 | { | ||
| 267 | if (!client || !callback) | ||
| 268 | return OSTRACE_E_INVALID_ARG; | ||
| 269 | |||
| 270 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 271 | |||
| 272 | if (client->worker) { | ||
| 273 | debug_info("Another ostrace activity thread appears to be running already."); | ||
| 274 | return res; | ||
| 275 | } | ||
| 276 | |||
| 277 | plist_t dict = plist_new_dict(); | ||
| 278 | plist_dict_set_item(dict, "Pid", plist_new_uint(0x0FFFFFFFF)); | ||
| 279 | plist_dict_set_item(dict, "MessageFilter", plist_new_uint(0xFFFF)); | ||
| 280 | plist_dict_set_item(dict, "StreamFlags", plist_new_uint(0x3C)); | ||
| 281 | if (options) { | ||
| 282 | plist_dict_merge(&dict, options); | ||
| 283 | } | ||
| 284 | plist_dict_set_item(dict, "Request", plist_new_string("StartActivity")); | ||
| 285 | |||
| 286 | res = ostrace_send_plist(client, dict); | ||
| 287 | plist_free(dict); | ||
| 288 | if (res != OSTRACE_E_SUCCESS) { | ||
| 289 | return res; | ||
| 290 | } | ||
| 291 | |||
| 292 | dict = NULL; | ||
| 293 | res = ostrace_receive_plist(client, &dict); | ||
| 294 | if (res != OSTRACE_E_SUCCESS) { | ||
| 295 | return res; | ||
| 296 | } | ||
| 297 | res = _ostrace_check_result(dict); | ||
| 298 | if (res != OSTRACE_E_SUCCESS) { | ||
| 299 | return res; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* start worker thread */ | ||
| 303 | struct ostrace_worker_thread *oswt = (struct ostrace_worker_thread*)malloc(sizeof(struct ostrace_worker_thread)); | ||
| 304 | if (oswt) { | ||
| 305 | oswt->client = client; | ||
| 306 | oswt->cbfunc = callback; | ||
| 307 | oswt->user_data = user_data; | ||
| 308 | |||
| 309 | if (thread_new(&client->worker, ostrace_worker, oswt) == 0) { | ||
| 310 | res = OSTRACE_E_SUCCESS; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | return res; | ||
| 315 | } | ||
| 316 | |||
| 317 | ostrace_error_t ostrace_stop_activity(ostrace_client_t client) | ||
| 318 | { | ||
| 319 | if (client->worker) { | ||
| 320 | /* notify thread to finish */ | ||
| 321 | service_client_t parent = client->parent; | ||
| 322 | client->parent = NULL; | ||
| 323 | /* join thread to make it exit */ | ||
| 324 | thread_join(client->worker); | ||
| 325 | thread_free(client->worker); | ||
| 326 | client->worker = THREAD_T_NULL; | ||
| 327 | client->parent = parent; | ||
| 328 | } | ||
| 329 | |||
| 330 | return OSTRACE_E_SUCCESS; | ||
| 331 | } | ||
| 332 | |||
| 333 | ostrace_error_t ostrace_get_pid_list(ostrace_client_t client, plist_t* list) | ||
| 334 | { | ||
| 335 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 336 | plist_t dict = plist_new_dict(); | ||
| 337 | plist_dict_set_item(dict, "Request", plist_new_string("PidList")); | ||
| 338 | |||
| 339 | if (!client || !list) { | ||
| 340 | return OSTRACE_E_INVALID_ARG; | ||
| 341 | } | ||
| 342 | |||
| 343 | res = ostrace_send_plist(client, dict); | ||
| 344 | plist_free(dict); | ||
| 345 | if (res != OSTRACE_E_SUCCESS) { | ||
| 346 | return res; | ||
| 347 | } | ||
| 348 | |||
| 349 | plist_t reply = NULL; | ||
| 350 | res = ostrace_receive_plist(client, &reply); | ||
| 351 | if (res != OSTRACE_E_SUCCESS) { | ||
| 352 | return res; | ||
| 353 | } | ||
| 354 | res = _ostrace_check_result(reply); | ||
| 355 | if (res != OSTRACE_E_SUCCESS) { | ||
| 356 | return res; | ||
| 357 | } | ||
| 358 | |||
| 359 | plist_t payload = plist_dict_get_item(reply, "Payload"); | ||
| 360 | if (!payload) { | ||
| 361 | return OSTRACE_E_REQUEST_FAILED; | ||
| 362 | } | ||
| 363 | *list = plist_copy(payload); | ||
| 364 | plist_free(reply); | ||
| 365 | |||
| 366 | return OSTRACE_E_SUCCESS; | ||
| 367 | } | ||
| 368 | |||
| 369 | ostrace_error_t ostrace_create_archive(ostrace_client_t client, plist_t options, ostrace_archive_write_cb_t callback, void* user_data) | ||
| 370 | { | ||
| 371 | ostrace_error_t res = OSTRACE_E_UNKNOWN_ERROR; | ||
| 372 | if (!client || !callback) { | ||
| 373 | return OSTRACE_E_INVALID_ARG; | ||
| 374 | } | ||
| 375 | plist_t dict = plist_new_dict(); | ||
| 376 | if (options) { | ||
| 377 | plist_dict_merge(&dict, options); | ||
| 378 | } | ||
| 379 | plist_dict_set_item(dict, "Request", plist_new_string("CreateArchive")); | ||
| 380 | |||
| 381 | res = ostrace_send_plist(client, dict); | ||
| 382 | plist_free(dict); | ||
| 383 | if (res != OSTRACE_E_SUCCESS) { | ||
| 384 | return res; | ||
| 385 | } | ||
| 386 | |||
| 387 | plist_t reply = NULL; | ||
| 388 | res = ostrace_receive_plist(client, &reply); | ||
| 389 | if (res != OSTRACE_E_SUCCESS) { | ||
| 390 | return res; | ||
| 391 | } | ||
| 392 | |||
| 393 | res = _ostrace_check_result(reply); | ||
| 394 | if (res != OSTRACE_E_SUCCESS) { | ||
| 395 | return res; | ||
| 396 | } | ||
| 397 | |||
| 398 | debug_info("Receiving archive...\n"); | ||
| 399 | while (1) { | ||
| 400 | uint8_t msgtype = 0; | ||
| 401 | uint32_t received = 0; | ||
| 402 | res = ostrace_error(service_receive(client->parent, (char*)&msgtype, 1, &received)); | ||
| 403 | if (res != OSTRACE_E_SUCCESS) { | ||
| 404 | debug_info("Could not read message type from service: %d", res); | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | if (msgtype != 3) { | ||
| 408 | debug_info("Unexpected packet type %d", msgtype); | ||
| 409 | return OSTRACE_E_REQUEST_FAILED; | ||
| 410 | } | ||
| 411 | uint32_t rlen = 0; | ||
| 412 | res = ostrace_error(service_receive(client->parent, (char*)&rlen, 4, &received)); | ||
| 413 | if (res != OSTRACE_E_SUCCESS) { | ||
| 414 | debug_info("Failed to read message size from service"); | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | |||
| 418 | rlen = le32toh(rlen); | ||
| 419 | debug_info("got length %d", rlen); | ||
| 420 | |||
| 421 | unsigned char* buf = (unsigned char*)malloc(rlen); | ||
| 422 | res = ostrace_error(service_receive(client->parent, (char*)buf, rlen, &received)); | ||
| 423 | if (res != OSTRACE_E_SUCCESS) { | ||
| 424 | debug_info("Could not read data from service: %d", res); | ||
| 425 | break; | ||
| 426 | } | ||
| 427 | if (callback(buf, received, user_data) < 0) { | ||
| 428 | debug_info("Aborted through callback"); | ||
| 429 | return OSTRACE_E_REQUEST_FAILED; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | debug_info("Done.\n"); | ||
| 433 | |||
| 434 | return OSTRACE_E_SUCCESS; | ||
| 435 | } | ||
| 436 | |||
diff --git a/src/ostrace.h b/src/ostrace.h new file mode 100644 index 0000000..dcc3e8d --- /dev/null +++ b/src/ostrace.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * ostrace.h | ||
| 3 | * com.apple.os_trace_relay service header file. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2020-2025 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _OSTRACE_H | ||
| 23 | #define _OSTRACE_H | ||
| 24 | |||
| 25 | #include "idevice.h" | ||
| 26 | #include "libimobiledevice/ostrace.h" | ||
| 27 | #include "service.h" | ||
| 28 | #include <libimobiledevice-glue/thread.h> | ||
| 29 | |||
| 30 | struct ostrace_client_private { | ||
| 31 | service_client_t parent; | ||
| 32 | THREAD_T worker; | ||
| 33 | }; | ||
| 34 | |||
| 35 | void *ostrace_worker(void *arg); | ||
| 36 | |||
| 37 | #endif | ||
diff --git a/src/sbservices.c b/src/sbservices.c index 365e130..5df5122 100644 --- a/src/sbservices.c +++ b/src/sbservices.c | |||
| @@ -24,7 +24,11 @@ | |||
| 24 | #endif | 24 | #endif |
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | |||
| 28 | #ifndef _MSC_VER | ||
| 27 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | #endif | ||
| 31 | |||
| 28 | #include <plist/plist.h> | 32 | #include <plist/plist.h> |
| 29 | 33 | ||
| 30 | #include "sbservices.h" | 34 | #include "sbservices.h" |
diff --git a/tools/Makefile.am b/tools/Makefile.am index 7c9060b..24cfc66 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am | |||
| @@ -35,7 +35,7 @@ bin_PROGRAMS = \ | |||
| 35 | afcclient | 35 | afcclient |
| 36 | 36 | ||
| 37 | idevicebtlogger_SOURCES = idevicebtlogger.c | 37 | idevicebtlogger_SOURCES = idevicebtlogger.c |
| 38 | iidevicebtlogger_CFLAGS = $(AM_CFLAGS) | 38 | idevicebtlogger_CFLAGS = $(AM_CFLAGS) |
| 39 | idevicebtlogger_LDFLAGS = $(top_builddir)/common/libinternalcommon.la $(AM_LDFLAGS) | 39 | idevicebtlogger_LDFLAGS = $(top_builddir)/common/libinternalcommon.la $(AM_LDFLAGS) |
| 40 | idevicebtlogger_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la | 40 | idevicebtlogger_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la |
| 41 | 41 | ||
| @@ -51,8 +51,8 @@ idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la | |||
| 51 | 51 | ||
| 52 | idevicepair_SOURCES = idevicepair.c | 52 | idevicepair_SOURCES = idevicepair.c |
| 53 | idevicepair_CFLAGS = $(AM_CFLAGS) | 53 | idevicepair_CFLAGS = $(AM_CFLAGS) |
| 54 | idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS) | 54 | idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) |
| 55 | idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) | 55 | idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) $(ssl_lib_LIBS) |
| 56 | 56 | ||
| 57 | idevicesyslog_SOURCES = idevicesyslog.c | 57 | idevicesyslog_SOURCES = idevicesyslog.c |
| 58 | idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) | 58 | idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) |
| @@ -76,7 +76,7 @@ idevicebackup2_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la | |||
| 76 | 76 | ||
| 77 | ideviceimagemounter_SOURCES = ideviceimagemounter.c | 77 | ideviceimagemounter_SOURCES = ideviceimagemounter.c |
| 78 | ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) $(libtatsu_CFLAGS) | 78 | ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) $(libtatsu_CFLAGS) |
| 79 | ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(ssl_lib_LIBS) $(libtatsu_LIBS) | 79 | ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) $(libtatsu_LIBS) |
| 80 | ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la | 80 | ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la |
| 81 | 81 | ||
| 82 | idevicescreenshot_SOURCES = idevicescreenshot.c | 82 | idevicescreenshot_SOURCES = idevicescreenshot.c |
| @@ -135,8 +135,8 @@ idevicesetlocation_LDFLAGS = $(AM_LDFLAGS) | |||
| 135 | idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la | 135 | idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la |
| 136 | 136 | ||
| 137 | afcclient_SOURCES = afcclient.c | 137 | afcclient_SOURCES = afcclient.c |
| 138 | afcclient_CFLAGS = $(AM_CFLAGS) | 138 | afcclient_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) |
| 139 | afcclient_LDFLAGS = $(AM_LDFLAGS) | 139 | afcclient_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) |
| 140 | if HAVE_READLINE | 140 | if HAVE_READLINE |
| 141 | afcclient_CFLAGS += $(readline_CFLAGS) | 141 | afcclient_CFLAGS += $(readline_CFLAGS) |
| 142 | afcclient_LDFLAGS += $(readline_LIBS) | 142 | afcclient_LDFLAGS += $(readline_LIBS) |
diff --git a/tools/afcclient.c b/tools/afcclient.c index 8f49831..2667e52 100644 --- a/tools/afcclient.c +++ b/tools/afcclient.c | |||
| @@ -38,8 +38,9 @@ | |||
| 38 | #include <unistd.h> | 38 | #include <unistd.h> |
| 39 | #include <dirent.h> | 39 | #include <dirent.h> |
| 40 | #include <time.h> | 40 | #include <time.h> |
| 41 | #include <sys/stat.h> | ||
| 41 | 42 | ||
| 42 | #ifdef WIN32 | 43 | #ifdef _WIN32 |
| 43 | #include <windows.h> | 44 | #include <windows.h> |
| 44 | #include <sys/time.h> | 45 | #include <sys/time.h> |
| 45 | #include <conio.h> | 46 | #include <conio.h> |
| @@ -95,7 +96,7 @@ static size_t curdir_len = 0; | |||
| 95 | static int file_exists(const char* path) | 96 | static int file_exists(const char* path) |
| 96 | { | 97 | { |
| 97 | struct stat tst; | 98 | struct stat tst; |
| 98 | #ifdef WIN32 | 99 | #ifdef _WIN32 |
| 99 | return (stat(path, &tst) == 0); | 100 | return (stat(path, &tst) == 0); |
| 100 | #else | 101 | #else |
| 101 | return (lstat(path, &tst) == 0); | 102 | return (lstat(path, &tst) == 0); |
| @@ -105,7 +106,7 @@ static int file_exists(const char* path) | |||
| 105 | static int is_directory(const char* path) | 106 | static int is_directory(const char* path) |
| 106 | { | 107 | { |
| 107 | struct stat tst; | 108 | struct stat tst; |
| 108 | #ifdef WIN32 | 109 | #ifdef _WIN32 |
| 109 | return (stat(path, &tst) == 0) && S_ISDIR(tst.st_mode); | 110 | return (stat(path, &tst) == 0) && S_ISDIR(tst.st_mode); |
| 110 | #else | 111 | #else |
| 111 | return (lstat(path, &tst) == 0) && S_ISDIR(tst.st_mode); | 112 | return (lstat(path, &tst) == 0) && S_ISDIR(tst.st_mode); |
| @@ -138,8 +139,9 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 138 | } | 139 | } |
| 139 | 140 | ||
| 140 | #ifndef HAVE_READLINE | 141 | #ifndef HAVE_READLINE |
| 141 | #ifdef WIN32 | 142 | #ifdef _WIN32 |
| 142 | #define BS_CC '\b' | 143 | #define BS_CC '\b' |
| 144 | #define getch _getch | ||
| 143 | #else | 145 | #else |
| 144 | #define BS_CC 0x7f | 146 | #define BS_CC 0x7f |
| 145 | #define getch getchar | 147 | #define getch getchar |
| @@ -154,12 +156,18 @@ static void get_input(char *buf, int maxlen) | |||
| 154 | break; | 156 | break; |
| 155 | } | 157 | } |
| 156 | if (isprint(c)) { | 158 | if (isprint(c)) { |
| 157 | if (len < maxlen-1) | 159 | if (len < maxlen-1) { |
| 158 | buf[len++] = c; | 160 | buf[len++] = c; |
| 161 | #ifdef _WIN32 | ||
| 162 | fputc(c, stdout); | ||
| 163 | #endif | ||
| 164 | } | ||
| 159 | } else if (c == BS_CC) { | 165 | } else if (c == BS_CC) { |
| 160 | if (len > 0) { | 166 | if (len > 0) { |
| 161 | fputs("\b \b", stdout); | 167 | fputs("\b \b", stdout); |
| 162 | len--; | 168 | len--; |
| 169 | } else { | ||
| 170 | fputc(0x07, stdout); | ||
| 163 | } | 171 | } |
| 164 | } | 172 | } |
| 165 | } | 173 | } |
| @@ -175,7 +183,7 @@ int stop_requested = 0; | |||
| 175 | static void handle_signal(int sig) | 183 | static void handle_signal(int sig) |
| 176 | { | 184 | { |
| 177 | stop_requested++; | 185 | stop_requested++; |
| 178 | #ifdef WIN32 | 186 | #ifdef _WIN32 |
| 179 | GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); | 187 | GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); |
| 180 | #else | 188 | #else |
| 181 | kill(getpid(), SIGINT); | 189 | kill(getpid(), SIGINT); |
| @@ -364,62 +372,55 @@ static char* get_realpath(const char* path) | |||
| 364 | 372 | ||
| 365 | static void handle_devinfo(afc_client_t afc, int argc, char** argv) | 373 | static void handle_devinfo(afc_client_t afc, int argc, char** argv) |
| 366 | { | 374 | { |
| 367 | char **info = NULL; | 375 | plist_t info = NULL; |
| 368 | afc_error_t err = afc_get_device_info(afc, &info); | 376 | afc_error_t err = afc_get_device_info_plist(afc, &info); |
| 369 | if (err == AFC_E_SUCCESS && info) { | 377 | if (err == AFC_E_SUCCESS && info) { |
| 370 | int i; | 378 | if (argc > 0 && !strcmp(argv[0], "--plain")) { |
| 371 | for (i = 0; info[i]; i += 2) { | 379 | plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE); |
| 372 | printf("%s: %s\n", info[i], info[i+1]); | 380 | } else { |
| 381 | plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE); | ||
| 373 | } | 382 | } |
| 374 | } else { | 383 | } else { |
| 375 | printf("Error: Failed to get device info: %s (%d)\n", afc_strerror(err), err); | 384 | printf("Error: Failed to get device info: %s (%d)\n", afc_strerror(err), err); |
| 376 | } | 385 | } |
| 377 | afc_dictionary_free(info); | 386 | plist_free(info); |
| 378 | } | 387 | } |
| 379 | 388 | ||
| 380 | static int get_file_info_stat(afc_client_t afc, const char* path, struct afc_file_stat *stbuf) | 389 | static int get_file_info_stat(afc_client_t afc, const char* path, struct afc_file_stat *stbuf) |
| 381 | { | 390 | { |
| 382 | char **info = NULL; | 391 | plist_t info = NULL; |
| 383 | afc_error_t ret = afc_get_file_info(afc, path, &info); | 392 | afc_error_t ret = afc_get_file_info_plist(afc, path, &info); |
| 384 | memset(stbuf, 0, sizeof(struct afc_file_stat)); | 393 | memset(stbuf, 0, sizeof(struct afc_file_stat)); |
| 385 | if (ret != AFC_E_SUCCESS) { | 394 | if (ret != AFC_E_SUCCESS) { |
| 386 | return -1; | 395 | return -1; |
| 387 | } else if (!info) { | 396 | } else if (!info) { |
| 388 | return -1; | 397 | return -1; |
| 389 | } else { | ||
| 390 | // get file attributes from info list | ||
| 391 | int i; | ||
| 392 | for (i = 0; info[i]; i += 2) { | ||
| 393 | if (!strcmp(info[i], "st_size")) { | ||
| 394 | stbuf->st_size = atoll(info[i+1]); | ||
| 395 | } else if (!strcmp(info[i], "st_blocks")) { | ||
| 396 | stbuf->st_blocks = atoi(info[i+1]); | ||
| 397 | } else if (!strcmp(info[i], "st_ifmt")) { | ||
| 398 | if (!strcmp(info[i+1], "S_IFREG")) { | ||
| 399 | stbuf->st_mode = S_IFREG; | ||
| 400 | } else if (!strcmp(info[i+1], "S_IFDIR")) { | ||
| 401 | stbuf->st_mode = S_IFDIR; | ||
| 402 | } else if (!strcmp(info[i+1], "S_IFLNK")) { | ||
| 403 | stbuf->st_mode = S_IFLNK; | ||
| 404 | } else if (!strcmp(info[i+1], "S_IFBLK")) { | ||
| 405 | stbuf->st_mode = S_IFBLK; | ||
| 406 | } else if (!strcmp(info[i+1], "S_IFCHR")) { | ||
| 407 | stbuf->st_mode = S_IFCHR; | ||
| 408 | } else if (!strcmp(info[i+1], "S_IFIFO")) { | ||
| 409 | stbuf->st_mode = S_IFIFO; | ||
| 410 | } else if (!strcmp(info[i+1], "S_IFSOCK")) { | ||
| 411 | stbuf->st_mode = S_IFSOCK; | ||
| 412 | } | ||
| 413 | } else if (!strcmp(info[i], "st_nlink")) { | ||
| 414 | stbuf->st_nlink = atoi(info[i+1]); | ||
| 415 | } else if (!strcmp(info[i], "st_mtime")) { | ||
| 416 | stbuf->st_mtime = (time_t)(atoll(info[i+1]) / 1000000000); | ||
| 417 | } else if (!strcmp(info[i], "st_birthtime")) { /* available on iOS 7+ */ | ||
| 418 | stbuf->st_birthtime = (time_t)(atoll(info[i+1]) / 1000000000); | ||
| 419 | } | ||
| 420 | } | ||
| 421 | afc_dictionary_free(info); | ||
| 422 | } | 398 | } |
| 399 | stbuf->st_size = plist_dict_get_uint(info, "st_size"); | ||
| 400 | stbuf->st_blocks = plist_dict_get_uint(info, "st_blocks"); | ||
| 401 | const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL); | ||
| 402 | if (s_ifmt) { | ||
| 403 | if (!strcmp(s_ifmt, "S_IFREG")) { | ||
| 404 | stbuf->st_mode = S_IFREG; | ||
| 405 | } else if (!strcmp(s_ifmt, "S_IFDIR")) { | ||
| 406 | stbuf->st_mode = S_IFDIR; | ||
| 407 | } else if (!strcmp(s_ifmt, "S_IFLNK")) { | ||
| 408 | stbuf->st_mode = S_IFLNK; | ||
| 409 | } else if (!strcmp(s_ifmt, "S_IFBLK")) { | ||
| 410 | stbuf->st_mode = S_IFBLK; | ||
| 411 | } else if (!strcmp(s_ifmt, "S_IFCHR")) { | ||
| 412 | stbuf->st_mode = S_IFCHR; | ||
| 413 | } else if (!strcmp(s_ifmt, "S_IFIFO")) { | ||
| 414 | stbuf->st_mode = S_IFIFO; | ||
| 415 | } else if (!strcmp(s_ifmt, "S_IFSOCK")) { | ||
| 416 | stbuf->st_mode = S_IFSOCK; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | stbuf->st_nlink = plist_dict_get_uint(info, "st_nlink"); | ||
| 420 | stbuf->st_mtime = (time_t)(plist_dict_get_uint(info, "st_mtime") / 1000000000); | ||
| 421 | /* available on iOS 7+ */ | ||
| 422 | stbuf->st_birthtime = (time_t)(plist_dict_get_uint(info, "st_birthtime") / 1000000000); | ||
| 423 | plist_free(info); | ||
| 423 | return 0; | 424 | return 0; |
| 424 | } | 425 | } |
| 425 | 426 | ||
| @@ -430,22 +431,23 @@ static void handle_file_info(afc_client_t afc, int argc, char** argv) | |||
| 430 | return; | 431 | return; |
| 431 | } | 432 | } |
| 432 | 433 | ||
| 433 | char **info = NULL; | 434 | plist_t info = NULL; |
| 434 | char* abspath = get_absolute_path(argv[0]); | 435 | char* abspath = get_absolute_path(argv[0]); |
| 435 | if (!abspath) { | 436 | if (!abspath) { |
| 436 | printf("Error: Invalid argument\n"); | 437 | printf("Error: Invalid argument\n"); |
| 437 | return; | 438 | return; |
| 438 | } | 439 | } |
| 439 | afc_error_t err = afc_get_file_info(afc, abspath, &info); | 440 | afc_error_t err = afc_get_file_info_plist(afc, abspath, &info); |
| 440 | if (err == AFC_E_SUCCESS && info) { | 441 | if (err == AFC_E_SUCCESS && info) { |
| 441 | int i; | 442 | if (argc > 1 && !strcmp(argv[1], "--plain")) { |
| 442 | for (i = 0; info[i]; i += 2) { | 443 | plist_write_to_stream(info, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_NONE); |
| 443 | printf("%s: %s\n", info[i], info[i+1]); | 444 | } else { |
| 445 | plist_write_to_stream(info, stdout, PLIST_FORMAT_JSON, PLIST_OPT_NONE); | ||
| 444 | } | 446 | } |
| 445 | } else { | 447 | } else { |
| 446 | printf("Error: Failed to get file info for %s: %s (%d)\n", argv[0], afc_strerror(err), err); | 448 | printf("Error: Failed to get file info for %s: %s (%d)\n", argv[0], afc_strerror(err), err); |
| 447 | } | 449 | } |
| 448 | afc_dictionary_free(info); | 450 | plist_free(info); |
| 449 | free(abspath); | 451 | free(abspath); |
| 450 | } | 452 | } |
| 451 | 453 | ||
| @@ -483,7 +485,7 @@ static void print_file_info(afc_client_t afc, const char* path, int list_verbose | |||
| 483 | printf(" "); | 485 | printf(" "); |
| 484 | printf("%10lld", (long long)st.st_size); | 486 | printf("%10lld", (long long)st.st_size); |
| 485 | printf(" "); | 487 | printf(" "); |
| 486 | #ifdef WIN32 | 488 | #ifdef _WIN32 |
| 487 | strftime(timebuf, 64, "%d %b %Y %H:%M:%S", localtime(&t)); | 489 | strftime(timebuf, 64, "%d %b %Y %H:%M:%S", localtime(&t)); |
| 488 | #else | 490 | #else |
| 489 | strftime(timebuf, 64, "%d %h %Y %H:%M:%S", localtime(&t)); | 491 | strftime(timebuf, 64, "%d %h %Y %H:%M:%S", localtime(&t)); |
| @@ -774,7 +776,7 @@ static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char | |||
| 774 | 776 | ||
| 775 | static int __mkdir(const char* path) | 777 | static int __mkdir(const char* path) |
| 776 | { | 778 | { |
| 777 | #ifdef WIN32 | 779 | #ifdef _WIN32 |
| 778 | return mkdir(path); | 780 | return mkdir(path); |
| 779 | #else | 781 | #else |
| 780 | return mkdir(path, 0755); | 782 | return mkdir(path, 0755); |
| @@ -783,28 +785,19 @@ static int __mkdir(const char* path) | |||
| 783 | 785 | ||
| 784 | static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get) | 786 | static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get) |
| 785 | { | 787 | { |
| 786 | char **info = NULL; | 788 | plist_t info = NULL; |
| 787 | uint64_t file_size = 0; | 789 | uint64_t file_size = 0; |
| 788 | afc_error_t err = afc_get_file_info(afc, srcpath, &info); | 790 | afc_error_t err = afc_get_file_info_plist(afc, srcpath, &info); |
| 789 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 791 | if (err == AFC_E_OBJECT_NOT_FOUND) { |
| 790 | printf("Error: Failed to read from file '%s': %s (%d)\n", srcpath, afc_strerror(err), err); | 792 | printf("Error: Failed to read from file '%s': %s (%d)\n", srcpath, afc_strerror(err), err); |
| 791 | return 0; | 793 | return 0; |
| 792 | } | 794 | } |
| 793 | uint8_t is_dir = 0; | 795 | uint8_t is_dir = 0; |
| 794 | if (info) { | 796 | if (info) { |
| 795 | char **p = info; | 797 | file_size = plist_dict_get_uint(info, "st_size"); |
| 796 | while (p && *p) { | 798 | const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL); |
| 797 | if (!strcmp(*p, "st_size")) { | 799 | is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR")); |
| 798 | p++; | 800 | plist_free(info); |
| 799 | file_size = (uint64_t) strtoull(*p, NULL, 10); | ||
| 800 | } | ||
| 801 | if (!strcmp(*p, "st_ifmt")) { | ||
| 802 | p++; | ||
| 803 | is_dir = !strcmp(*p, "S_IFDIR"); | ||
| 804 | } | ||
| 805 | p++; | ||
| 806 | } | ||
| 807 | afc_dictionary_free(info); | ||
| 808 | } | 801 | } |
| 809 | uint8_t succeed = 1; | 802 | uint8_t succeed = 1; |
| 810 | if (is_dir) { | 803 | if (is_dir) { |
| @@ -837,7 +830,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 837 | p++; | 830 | p++; |
| 838 | continue; | 831 | continue; |
| 839 | } | 832 | } |
| 840 | size_t len = srcpath_is_root ? strlen(*p) + 1 : srcpath_len + 1 + strlen(*p) + 1; | 833 | size_t len = srcpath_is_root ? (strlen(*p) + 2) : (srcpath_len + 1 + strlen(*p) + 1); |
| 841 | char *testpath = (char *) malloc(len); | 834 | char *testpath = (char *) malloc(len); |
| 842 | if (srcpath_is_root) { | 835 | if (srcpath_is_root) { |
| 843 | snprintf(testpath, len, "/%s", *p); | 836 | snprintf(testpath, len, "/%s", *p); |
| @@ -845,7 +838,7 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 845 | snprintf(testpath, len, "%s/%s", srcpath, *p); | 838 | snprintf(testpath, len, "%s/%s", srcpath, *p); |
| 846 | } | 839 | } |
| 847 | uint8_t dst_is_root = strcmp(srcpath, "/") == 0; | 840 | uint8_t dst_is_root = strcmp(srcpath, "/") == 0; |
| 848 | size_t dst_len = dst_is_root ? strlen(*p) + 1 : strlen(dstpath) + 1 + strlen(*p) + 1; | 841 | size_t dst_len = dst_is_root ? (strlen(*p) + 2) : (strlen(dstpath) + 1 + strlen(*p) + 1); |
| 849 | char *newdst = (char *) malloc(dst_len); | 842 | char *newdst = (char *) malloc(dst_len); |
| 850 | if (dst_is_root) { | 843 | if (dst_is_root) { |
| 851 | snprintf(newdst, dst_len, "/%s", *p); | 844 | snprintf(newdst, dst_len, "/%s", *p); |
| @@ -921,9 +914,9 @@ static void handle_get(afc_client_t afc, int argc, char **argv) | |||
| 921 | 914 | ||
| 922 | // target is a directory, put file under this target | 915 | // target is a directory, put file under this target |
| 923 | if (is_directory(dstpath)) { | 916 | if (is_directory(dstpath)) { |
| 924 | const char *basen = path_get_basename(argv[0]); | 917 | const char *basen = path_get_basename(srcpath); |
| 925 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 918 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; |
| 926 | size_t len = dst_is_root ? (strlen(basen) + 1) : (strlen(dstpath) + 1 + strlen(basen) + 1); | 919 | size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1); |
| 927 | char *newdst = (char *) malloc(len); | 920 | char *newdst = (char *) malloc(len); |
| 928 | if (dst_is_root) { | 921 | if (dst_is_root) { |
| 929 | snprintf(newdst, len, "/%s", basen); | 922 | snprintf(newdst, len, "/%s", basen); |
| @@ -944,11 +937,11 @@ static void handle_get(afc_client_t afc, int argc, char **argv) | |||
| 944 | 937 | ||
| 945 | static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite) | 938 | static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite) |
| 946 | { | 939 | { |
| 947 | char **info = NULL; | 940 | plist_t info = NULL; |
| 948 | afc_error_t ret = afc_get_file_info(afc, dstpath, &info); | 941 | afc_error_t ret = afc_get_file_info_plist(afc, dstpath, &info); |
| 949 | // file exists, only overwrite with '-f' option was set | 942 | // file exists, only overwrite with '-f' option was set |
| 950 | if (ret == AFC_E_SUCCESS && info) { | 943 | if (ret == AFC_E_SUCCESS && info) { |
| 951 | afc_dictionary_free(info); | 944 | plist_free(info); |
| 952 | if (!force_overwrite) { | 945 | if (!force_overwrite) { |
| 953 | printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath); | 946 | printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath); |
| 954 | return 0; | 947 | return 0; |
| @@ -1016,6 +1009,9 @@ static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char | |||
| 1016 | } | 1009 | } |
| 1017 | } | 1010 | } |
| 1018 | } | 1011 | } |
| 1012 | if (progress) { | ||
| 1013 | printf("\n"); | ||
| 1014 | } | ||
| 1019 | free(buf); | 1015 | free(buf); |
| 1020 | afc_file_close(afc, fh); | 1016 | afc_file_close(afc, fh); |
| 1021 | fclose(f); | 1017 | fclose(f); |
| @@ -1029,10 +1025,11 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 1029 | printf("Error: Failed to put directory without '-r' option: %s\n", srcpath); | 1025 | printf("Error: Failed to put directory without '-r' option: %s\n", srcpath); |
| 1030 | return 0; | 1026 | return 0; |
| 1031 | } | 1027 | } |
| 1032 | char **info = NULL; | 1028 | plist_t info = NULL; |
| 1033 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 1029 | afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info); |
| 1034 | //create if target directory does not exist | 1030 | //create if target directory does not exist |
| 1035 | afc_dictionary_free(info); | 1031 | plist_free(info); |
| 1032 | info = NULL; | ||
| 1036 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 1033 | if (err == AFC_E_OBJECT_NOT_FOUND) { |
| 1037 | err = afc_make_directory(afc, dstpath); | 1034 | err = afc_make_directory(afc, dstpath); |
| 1038 | if (err != AFC_E_SUCCESS) { | 1035 | if (err != AFC_E_SUCCESS) { |
| @@ -1043,19 +1040,12 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 1043 | printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath); | 1040 | printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath); |
| 1044 | return 0; | 1041 | return 0; |
| 1045 | } | 1042 | } |
| 1046 | afc_get_file_info(afc, dstpath, &info); | 1043 | afc_get_file_info_plist(afc, dstpath, &info); |
| 1047 | uint8_t is_dir = 0; | 1044 | uint8_t is_dir = 0; |
| 1048 | if (info) { | 1045 | if (info) { |
| 1049 | char **p = info; | 1046 | const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL); |
| 1050 | while (p && *p) { | 1047 | is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR")); |
| 1051 | if (!strcmp(*p, "st_ifmt")) { | 1048 | plist_free(info); |
| 1052 | p++; | ||
| 1053 | is_dir = !strcmp(*p, "S_IFDIR"); | ||
| 1054 | break; | ||
| 1055 | } | ||
| 1056 | p++; | ||
| 1057 | } | ||
| 1058 | afc_dictionary_free(info); | ||
| 1059 | } | 1049 | } |
| 1060 | if (!is_dir) { | 1050 | if (!is_dir) { |
| 1061 | printf("Error: Failed to create or access directory: '%s'\n", dstpath); | 1051 | printf("Error: Failed to create or access directory: '%s'\n", dstpath); |
| @@ -1073,7 +1063,7 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 1073 | char *fpath = string_build_path(srcpath, ep->d_name, NULL); | 1063 | char *fpath = string_build_path(srcpath, ep->d_name, NULL); |
| 1074 | if (fpath) { | 1064 | if (fpath) { |
| 1075 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 1065 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; |
| 1076 | size_t len = dst_is_root ? strlen(ep->d_name) + 1 : strlen(dstpath) + 1 + strlen(ep->d_name) + 1; | 1066 | size_t len = dst_is_root ? (strlen(ep->d_name) + 2) : (strlen(dstpath) + 1 + strlen(ep->d_name) + 1); |
| 1077 | char *newdst = (char *) malloc(len); | 1067 | char *newdst = (char *) malloc(len); |
| 1078 | if (dst_is_root) { | 1068 | if (dst_is_root) { |
| 1079 | snprintf(newdst, len, "/%s", ep->d_name); | 1069 | snprintf(newdst, len, "/%s", ep->d_name); |
| @@ -1147,8 +1137,8 @@ static void handle_put(afc_client_t afc, int argc, char **argv) | |||
| 1147 | printf("Error: Invalid number of arguments\n"); | 1137 | printf("Error: Invalid number of arguments\n"); |
| 1148 | return; | 1138 | return; |
| 1149 | } | 1139 | } |
| 1150 | char **info = NULL; | 1140 | plist_t info = NULL; |
| 1151 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 1141 | afc_error_t err = afc_get_file_info_plist(afc, dstpath, &info); |
| 1152 | // target does not exist, put directly | 1142 | // target does not exist, put directly |
| 1153 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 1143 | if (err == AFC_E_OBJECT_NOT_FOUND) { |
| 1154 | put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); | 1144 | put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); |
| @@ -1157,22 +1147,15 @@ static void handle_put(afc_client_t afc, int argc, char **argv) | |||
| 1157 | } else { | 1147 | } else { |
| 1158 | uint8_t is_dir = 0; | 1148 | uint8_t is_dir = 0; |
| 1159 | if (info) { | 1149 | if (info) { |
| 1160 | char **p = info; | 1150 | const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL); |
| 1161 | while (p && *p) { | 1151 | is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR")); |
| 1162 | if (!strcmp(*p, "st_ifmt")) { | 1152 | plist_free(info); |
| 1163 | p++; | ||
| 1164 | is_dir = !strcmp(*p, "S_IFDIR"); | ||
| 1165 | break; | ||
| 1166 | } | ||
| 1167 | p++; | ||
| 1168 | } | ||
| 1169 | afc_dictionary_free(info); | ||
| 1170 | } | 1153 | } |
| 1171 | // target is a directory, try to put under this directory | 1154 | // target is a directory, try to put under this directory |
| 1172 | if (is_dir) { | 1155 | if (is_dir) { |
| 1173 | const char *basen = path_get_basename(srcpath); | 1156 | const char *basen = path_get_basename(srcpath); |
| 1174 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 1157 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; |
| 1175 | size_t len = dst_is_root ? strlen(basen) + 1 : strlen(dstpath) + 1 + strlen(basen) + 1; | 1158 | size_t len = dst_is_root ? (strlen(basen) + 2) : (strlen(dstpath) + 1 + strlen(basen) + 1); |
| 1176 | char *newdst = (char *) malloc(len); | 1159 | char *newdst = (char *) malloc(len); |
| 1177 | if (dst_is_root) { | 1160 | if (dst_is_root) { |
| 1178 | snprintf(newdst, len, "/%s", basen); | 1161 | snprintf(newdst, len, "/%s", basen); |
| @@ -1227,19 +1210,12 @@ static void handle_cd(afc_client_t afc, int argc, char** argv) | |||
| 1227 | 1210 | ||
| 1228 | char* path = get_realpath(argv[0]); | 1211 | char* path = get_realpath(argv[0]); |
| 1229 | int is_dir = 0; | 1212 | int is_dir = 0; |
| 1230 | char **info = NULL; | 1213 | plist_t info = NULL; |
| 1231 | afc_error_t err = afc_get_file_info(afc, path, &info); | 1214 | afc_error_t err = afc_get_file_info_plist(afc, path, &info); |
| 1232 | if (err == AFC_E_SUCCESS && info) { | 1215 | if (err == AFC_E_SUCCESS && info) { |
| 1233 | int i; | 1216 | const char* ifmt = plist_get_string_ptr(plist_dict_get_item(info, "st_ifmt"), NULL); |
| 1234 | for (i = 0; info[i]; i += 2) { | 1217 | is_dir = (ifmt && !strcmp(ifmt, "S_IFDIR")); |
| 1235 | if (!strcmp(info[i], "st_ifmt")) { | 1218 | plist_free(info); |
| 1236 | if (!strcmp(info[i+1], "S_IFDIR")) { | ||
| 1237 | is_dir = 1; | ||
| 1238 | } | ||
| 1239 | break; | ||
| 1240 | } | ||
| 1241 | } | ||
| 1242 | afc_dictionary_free(info); | ||
| 1243 | } else { | 1219 | } else { |
| 1244 | printf("Error: Failed to get file info for %s: %s (%d)\n", path, afc_strerror(err), err); | 1220 | printf("Error: Failed to get file info for %s: %s (%d)\n", path, afc_strerror(err), err); |
| 1245 | free(path); | 1221 | free(path); |
| @@ -1483,7 +1459,7 @@ int main(int argc, char** argv) | |||
| 1483 | }; | 1459 | }; |
| 1484 | 1460 | ||
| 1485 | signal(SIGTERM, handle_signal); | 1461 | signal(SIGTERM, handle_signal); |
| 1486 | #ifndef WIN32 | 1462 | #ifndef _WIN32 |
| 1487 | signal(SIGQUIT, handle_signal); | 1463 | signal(SIGQUIT, handle_signal); |
| 1488 | signal(SIGPIPE, SIG_IGN); | 1464 | signal(SIGPIPE, SIG_IGN); |
| 1489 | #endif | 1465 | #endif |
| @@ -1561,7 +1537,7 @@ int main(int argc, char** argv) | |||
| 1561 | idevice_events_subscribe(&context, device_event_cb, NULL); | 1537 | idevice_events_subscribe(&context, device_event_cb, NULL); |
| 1562 | 1538 | ||
| 1563 | while (!connected && !stop_requested) { | 1539 | while (!connected && !stop_requested) { |
| 1564 | #ifdef WIN32 | 1540 | #ifdef _WIN32 |
| 1565 | Sleep(100); | 1541 | Sleep(100); |
| 1566 | #else | 1542 | #else |
| 1567 | usleep(100000); | 1543 | usleep(100000); |
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c index c0537b8..363abad 100644 --- a/tools/idevicebackup.c +++ b/tools/idevicebackup.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <unistd.h> | 35 | #include <unistd.h> |
| 36 | #include <ctype.h> | 36 | #include <ctype.h> |
| 37 | #include <time.h> | 37 | #include <time.h> |
| 38 | #include <sys/stat.h> | ||
| 38 | 39 | ||
| 39 | #include <libimobiledevice/libimobiledevice.h> | 40 | #include <libimobiledevice/libimobiledevice.h> |
| 40 | #include <libimobiledevice/lockdown.h> | 41 | #include <libimobiledevice/lockdown.h> |
| @@ -51,7 +52,7 @@ | |||
| 51 | #define LOCK_ATTEMPTS 50 | 52 | #define LOCK_ATTEMPTS 50 |
| 52 | #define LOCK_WAIT 200000 | 53 | #define LOCK_WAIT 200000 |
| 53 | 54 | ||
| 54 | #ifdef WIN32 | 55 | #ifdef _WIN32 |
| 55 | #include <windows.h> | 56 | #include <windows.h> |
| 56 | #define sleep(x) Sleep(x*1000) | 57 | #define sleep(x) Sleep(x*1000) |
| 57 | #endif | 58 | #endif |
| @@ -175,7 +176,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid) | |||
| 175 | if (value_node) | 176 | if (value_node) |
| 176 | plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); | 177 | plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); |
| 177 | 178 | ||
| 178 | plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); | 179 | plist_dict_set_item(ret, "Last Backup Date", |
| 180 | #ifdef HAVE_PLIST_UNIX_DATE | ||
| 181 | plist_new_unix_date(time(NULL)) | ||
| 182 | #else | ||
| 183 | plist_new_date(time(NULL) - MAC_EPOCH, 0) | ||
| 184 | #endif | ||
| 185 | ); | ||
| 179 | 186 | ||
| 180 | value_node = plist_dict_get_item(root_node, "ProductType"); | 187 | value_node = plist_dict_get_item(root_node, "ProductType"); |
| 181 | plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); | 188 | plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); |
| @@ -212,7 +219,11 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist) | |||
| 212 | return; | 219 | return; |
| 213 | 220 | ||
| 214 | node = plist_dict_get_item(info_plist, "Last Backup Date"); | 221 | node = plist_dict_get_item(info_plist, "Last Backup Date"); |
| 222 | #ifdef HAVE_PLIST_UNIX_DATE | ||
| 223 | plist_set_unix_date_val(node, time(NULL)); | ||
| 224 | #else | ||
| 215 | plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0); | 225 | plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0); |
| 226 | #endif | ||
| 216 | 227 | ||
| 217 | node = NULL; | 228 | node = NULL; |
| 218 | } | 229 | } |
| @@ -642,7 +653,7 @@ int main(int argc, char *argv[]) | |||
| 642 | /* we need to exit cleanly on running backups and restores or we cause havok */ | 653 | /* we need to exit cleanly on running backups and restores or we cause havok */ |
| 643 | signal(SIGINT, clean_exit); | 654 | signal(SIGINT, clean_exit); |
| 644 | signal(SIGTERM, clean_exit); | 655 | signal(SIGTERM, clean_exit); |
| 645 | #ifndef WIN32 | 656 | #ifndef _WIN32 |
| 646 | signal(SIGQUIT, clean_exit); | 657 | signal(SIGQUIT, clean_exit); |
| 647 | signal(SIGPIPE, SIG_IGN); | 658 | signal(SIGPIPE, SIG_IGN); |
| 648 | #endif | 659 | #endif |
| @@ -1352,7 +1363,7 @@ files_out: | |||
| 1352 | file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata"); | 1363 | file_info_path = mobilebackup_build_path(backup_directory, hash, ".mddata"); |
| 1353 | 1364 | ||
| 1354 | /* determine file size */ | 1365 | /* determine file size */ |
| 1355 | #ifdef WIN32 | 1366 | #ifdef _WIN32 |
| 1356 | struct _stati64 fst; | 1367 | struct _stati64 fst; |
| 1357 | if (_stati64(file_info_path, &fst) != 0) | 1368 | if (_stati64(file_info_path, &fst) != 0) |
| 1358 | #else | 1369 | #else |
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c index c73b269..12d6083 100644 --- a/tools/idevicebackup2.c +++ b/tools/idevicebackup2.c | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | #define LOCK_ATTEMPTS 50 | 54 | #define LOCK_ATTEMPTS 50 |
| 55 | #define LOCK_WAIT 200000 | 55 | #define LOCK_WAIT 200000 |
| 56 | 56 | ||
| 57 | #ifdef WIN32 | 57 | #ifdef _WIN32 |
| 58 | #include <windows.h> | 58 | #include <windows.h> |
| 59 | #include <conio.h> | 59 | #include <conio.h> |
| 60 | #define sleep(x) Sleep(x*1000) | 60 | #define sleep(x) Sleep(x*1000) |
| @@ -74,6 +74,7 @@ | |||
| 74 | 74 | ||
| 75 | static int verbose = 1; | 75 | static int verbose = 1; |
| 76 | static int quit_flag = 0; | 76 | static int quit_flag = 0; |
| 77 | static int passcode_requested = 0; | ||
| 77 | 78 | ||
| 78 | #define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); }; | 79 | #define PRINT_VERBOSE(min_level, ...) if (verbose >= min_level) { printf(__VA_ARGS__); }; |
| 79 | 80 | ||
| @@ -115,6 +116,10 @@ static void notify_cb(const char *notification, void *userdata) | |||
| 115 | quit_flag++; | 116 | quit_flag++; |
| 116 | } else if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) { | 117 | } else if (!strcmp(notification, NP_BACKUP_DOMAIN_CHANGED)) { |
| 117 | backup_domain_changed = 1; | 118 | backup_domain_changed = 1; |
| 119 | } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.presented")) { | ||
| 120 | passcode_requested = 1; | ||
| 121 | } else if (!strcmp(notification, "com.apple.LocalAuthentication.ui.dismissed")) { | ||
| 122 | passcode_requested = 0; | ||
| 118 | } else { | 123 | } else { |
| 119 | PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification); | 124 | PRINT_VERBOSE(1, "Unhandled notification '%s' (TODO: implement)\n", notification); |
| 120 | } | 125 | } |
| @@ -126,21 +131,15 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil | |||
| 126 | return; | 131 | return; |
| 127 | } | 132 | } |
| 128 | 133 | ||
| 129 | char **fileinfo = NULL; | 134 | plist_t fileinfo = NULL; |
| 130 | uint32_t fsize = 0; | 135 | uint32_t fsize = 0; |
| 131 | 136 | ||
| 132 | afc_get_file_info(afc, filename, &fileinfo); | 137 | afc_get_file_info_plist(afc, filename, &fileinfo); |
| 133 | if (!fileinfo) { | 138 | if (!fileinfo) { |
| 134 | return; | 139 | return; |
| 135 | } | 140 | } |
| 136 | int i; | 141 | fsize = plist_dict_get_uint(fileinfo, "st_size"); |
| 137 | for (i = 0; fileinfo[i]; i+=2) { | 142 | plist_free(fileinfo); |
| 138 | if (!strcmp(fileinfo[i], "st_size")) { | ||
| 139 | fsize = atol(fileinfo[i+1]); | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | afc_dictionary_free(fileinfo); | ||
| 144 | 143 | ||
| 145 | if (fsize == 0) { | 144 | if (fsize == 0) { |
| 146 | return; | 145 | return; |
| @@ -173,7 +172,7 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil | |||
| 173 | 172 | ||
| 174 | static int __mkdir(const char* path, int mode) | 173 | static int __mkdir(const char* path, int mode) |
| 175 | { | 174 | { |
| 176 | #ifdef WIN32 | 175 | #ifdef _WIN32 |
| 177 | return mkdir(path); | 176 | return mkdir(path); |
| 178 | #else | 177 | #else |
| 179 | return mkdir(path, mode); | 178 | return mkdir(path, mode); |
| @@ -202,7 +201,7 @@ static int mkdir_with_parents(const char *dir, int mode) | |||
| 202 | return res; | 201 | return res; |
| 203 | } | 202 | } |
| 204 | 203 | ||
| 205 | #ifdef WIN32 | 204 | #ifdef _WIN32 |
| 206 | static int win32err_to_errno(int err_value) | 205 | static int win32err_to_errno(int err_value) |
| 207 | { | 206 | { |
| 208 | switch (err_value) { | 207 | switch (err_value) { |
| @@ -219,7 +218,7 @@ static int win32err_to_errno(int err_value) | |||
| 219 | static int remove_file(const char* path) | 218 | static int remove_file(const char* path) |
| 220 | { | 219 | { |
| 221 | int e = 0; | 220 | int e = 0; |
| 222 | #ifdef WIN32 | 221 | #ifdef _WIN32 |
| 223 | if (!DeleteFile(path)) { | 222 | if (!DeleteFile(path)) { |
| 224 | e = win32err_to_errno(GetLastError()); | 223 | e = win32err_to_errno(GetLastError()); |
| 225 | } | 224 | } |
| @@ -234,7 +233,7 @@ static int remove_file(const char* path) | |||
| 234 | static int remove_directory(const char* path) | 233 | static int remove_directory(const char* path) |
| 235 | { | 234 | { |
| 236 | int e = 0; | 235 | int e = 0; |
| 237 | #ifdef WIN32 | 236 | #ifdef _WIN32 |
| 238 | if (!RemoveDirectory(path)) { | 237 | if (!RemoveDirectory(path)) { |
| 239 | e = win32err_to_errno(GetLastError()); | 238 | e = win32err_to_errno(GetLastError()); |
| 240 | } | 239 | } |
| @@ -455,7 +454,13 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d | |||
| 455 | /* Installed Applications */ | 454 | /* Installed Applications */ |
| 456 | plist_dict_set_item(ret, "Installed Applications", installed_apps); | 455 | plist_dict_set_item(ret, "Installed Applications", installed_apps); |
| 457 | 456 | ||
| 458 | plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); | 457 | plist_dict_set_item(ret, "Last Backup Date", |
| 458 | #ifdef HAVE_PLIST_UNIX_DATE | ||
| 459 | plist_new_unix_date(time(NULL)) | ||
| 460 | #else | ||
| 461 | plist_new_date(time(NULL) - MAC_EPOCH, 0) | ||
| 462 | #endif | ||
| 463 | ); | ||
| 459 | 464 | ||
| 460 | value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); | 465 | value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); |
| 461 | if (value_node) | 466 | if (value_node) |
| @@ -768,7 +773,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char | |||
| 768 | uint32_t bytes = 0; | 773 | uint32_t bytes = 0; |
| 769 | char *localfile = string_build_path(backup_dir, path, NULL); | 774 | char *localfile = string_build_path(backup_dir, path, NULL); |
| 770 | char buf[32768]; | 775 | char buf[32768]; |
| 771 | #ifdef WIN32 | 776 | #ifdef _WIN32 |
| 772 | struct _stati64 fst; | 777 | struct _stati64 fst; |
| 773 | #else | 778 | #else |
| 774 | struct stat fst; | 779 | struct stat fst; |
| @@ -779,7 +784,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char | |||
| 779 | int errcode = -1; | 784 | int errcode = -1; |
| 780 | int result = -1; | 785 | int result = -1; |
| 781 | uint32_t length; | 786 | uint32_t length; |
| 782 | #ifdef WIN32 | 787 | #ifdef _WIN32 |
| 783 | uint64_t total; | 788 | uint64_t total; |
| 784 | uint64_t sent; | 789 | uint64_t sent; |
| 785 | #else | 790 | #else |
| @@ -810,7 +815,7 @@ static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char | |||
| 810 | goto leave_proto_err; | 815 | goto leave_proto_err; |
| 811 | } | 816 | } |
| 812 | 817 | ||
| 813 | #ifdef WIN32 | 818 | #ifdef _WIN32 |
| 814 | if (_stati64(localfile, &fst) < 0) | 819 | if (_stati64(localfile, &fst) < 0) |
| 815 | #else | 820 | #else |
| 816 | if (stat(localfile, &fst) < 0) | 821 | if (stat(localfile, &fst) < 0) |
| @@ -1218,7 +1223,12 @@ static void mb2_handle_list_directory(mobilebackup2_client_t mobilebackup2, plis | |||
| 1218 | plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype)); | 1223 | plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype)); |
| 1219 | plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); | 1224 | plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); |
| 1220 | plist_dict_set_item(fdict, "DLFileModificationDate", | 1225 | plist_dict_set_item(fdict, "DLFileModificationDate", |
| 1221 | plist_new_date(st.st_mtime - MAC_EPOCH, 0)); | 1226 | #ifdef HAVE_PLIST_UNIX_DATE |
| 1227 | plist_new_unix_date(st.st_mtime) | ||
| 1228 | #else | ||
| 1229 | plist_new_date(st.st_mtime - MAC_EPOCH, 0) | ||
| 1230 | #endif | ||
| 1231 | ); | ||
| 1222 | 1232 | ||
| 1223 | plist_dict_set_item(dirlist, ep->d_name, fdict); | 1233 | plist_dict_set_item(dirlist, ep->d_name, fdict); |
| 1224 | free(fpath); | 1234 | free(fpath); |
| @@ -1343,7 +1353,7 @@ static void mb2_copy_directory_by_path(const char *src, const char *dst) | |||
| 1343 | } | 1353 | } |
| 1344 | } | 1354 | } |
| 1345 | 1355 | ||
| 1346 | #ifdef WIN32 | 1356 | #ifdef _WIN32 |
| 1347 | #define BS_CC '\b' | 1357 | #define BS_CC '\b' |
| 1348 | #define my_getch getch | 1358 | #define my_getch getch |
| 1349 | #else | 1359 | #else |
| @@ -1463,8 +1473,6 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 1463 | ); | 1473 | ); |
| 1464 | } | 1474 | } |
| 1465 | 1475 | ||
| 1466 | #define DEVICE_VERSION(maj, min, patch) ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF)) | ||
| 1467 | |||
| 1468 | int main(int argc, char *argv[]) | 1476 | int main(int argc, char *argv[]) |
| 1469 | { | 1477 | { |
| 1470 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; | 1478 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; |
| @@ -1530,7 +1538,7 @@ int main(int argc, char *argv[]) | |||
| 1530 | /* we need to exit cleanly on running backups and restores or we cause havok */ | 1538 | /* we need to exit cleanly on running backups and restores or we cause havok */ |
| 1531 | signal(SIGINT, clean_exit); | 1539 | signal(SIGINT, clean_exit); |
| 1532 | signal(SIGTERM, clean_exit); | 1540 | signal(SIGTERM, clean_exit); |
| 1533 | #ifndef WIN32 | 1541 | #ifndef _WIN32 |
| 1534 | signal(SIGQUIT, clean_exit); | 1542 | signal(SIGQUIT, clean_exit); |
| 1535 | signal(SIGPIPE, SIG_IGN); | 1543 | signal(SIGPIPE, SIG_IGN); |
| 1536 | #endif | 1544 | #endif |
| @@ -1844,34 +1852,20 @@ int main(int argc, char *argv[]) | |||
| 1844 | } | 1852 | } |
| 1845 | 1853 | ||
| 1846 | /* get ProductVersion */ | 1854 | /* get ProductVersion */ |
| 1847 | char *product_version = NULL; | 1855 | int device_version = idevice_get_device_version(device); |
| 1848 | int device_version = 0; | ||
| 1849 | node_tmp = NULL; | ||
| 1850 | lockdownd_get_value(lockdown, NULL, "ProductVersion", &node_tmp); | ||
| 1851 | if (node_tmp) { | ||
| 1852 | if (plist_get_node_type(node_tmp) == PLIST_STRING) { | ||
| 1853 | plist_get_string_val(node_tmp, &product_version); | ||
| 1854 | } | ||
| 1855 | plist_free(node_tmp); | ||
| 1856 | node_tmp = NULL; | ||
| 1857 | } | ||
| 1858 | if (product_version) { | ||
| 1859 | int vers[3] = { 0, 0, 0 }; | ||
| 1860 | if (sscanf(product_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { | ||
| 1861 | device_version = DEVICE_VERSION(vers[0], vers[1], vers[2]); | ||
| 1862 | } | ||
| 1863 | } | ||
| 1864 | 1856 | ||
| 1865 | /* start notification_proxy */ | 1857 | /* start notification_proxy */ |
| 1866 | ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service); | 1858 | ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service); |
| 1867 | if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) { | 1859 | if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) { |
| 1868 | np_client_new(device, service, &np); | 1860 | np_client_new(device, service, &np); |
| 1869 | np_set_notify_callback(np, notify_cb, NULL); | 1861 | np_set_notify_callback(np, notify_cb, NULL); |
| 1870 | const char *noties[5] = { | 1862 | const char *noties[7] = { |
| 1871 | NP_SYNC_CANCEL_REQUEST, | 1863 | NP_SYNC_CANCEL_REQUEST, |
| 1872 | NP_SYNC_SUSPEND_REQUEST, | 1864 | NP_SYNC_SUSPEND_REQUEST, |
| 1873 | NP_SYNC_RESUME_REQUEST, | 1865 | NP_SYNC_RESUME_REQUEST, |
| 1874 | NP_BACKUP_DOMAIN_CHANGED, | 1866 | NP_BACKUP_DOMAIN_CHANGED, |
| 1867 | "com.apple.LocalAuthentication.ui.presented", | ||
| 1868 | "com.apple.LocalAuthentication.ui.dismissed", | ||
| 1875 | NULL | 1869 | NULL |
| 1876 | }; | 1870 | }; |
| 1877 | np_observe_notifications(np, noties); | 1871 | np_observe_notifications(np, noties); |
| @@ -2058,6 +2052,16 @@ checkpoint: | |||
| 2058 | } else { | 2052 | } else { |
| 2059 | PRINT_VERBOSE(1, "Incremental backup mode.\n"); | 2053 | PRINT_VERBOSE(1, "Incremental backup mode.\n"); |
| 2060 | } | 2054 | } |
| 2055 | if (device_version >= IDEVICE_DEVICE_VERSION(16,1,0)) { | ||
| 2056 | /* let's wait 2 second to see if the device passcode is requested */ | ||
| 2057 | int retries = 20; | ||
| 2058 | while (retries-- > 0 && !passcode_requested) { | ||
| 2059 | usleep(100000); | ||
| 2060 | } | ||
| 2061 | if (passcode_requested) { | ||
| 2062 | printf("*** Waiting for passcode to be entered on the device ***\n"); | ||
| 2063 | } | ||
| 2064 | } | ||
| 2061 | } else { | 2065 | } else { |
| 2062 | if (err == MOBILEBACKUP2_E_BAD_VERSION) { | 2066 | if (err == MOBILEBACKUP2_E_BAD_VERSION) { |
| 2063 | printf("ERROR: Could not start backup process: backup protocol version mismatch!\n"); | 2067 | printf("ERROR: Could not start backup process: backup protocol version mismatch!\n"); |
| @@ -2229,7 +2233,7 @@ checkpoint: | |||
| 2229 | if (newpw || backup_password) { | 2233 | if (newpw || backup_password) { |
| 2230 | mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts); | 2234 | mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts); |
| 2231 | uint8_t passcode_hint = 0; | 2235 | uint8_t passcode_hint = 0; |
| 2232 | if (device_version >= DEVICE_VERSION(13,0,0)) { | 2236 | if (device_version >= IDEVICE_DEVICE_VERSION(13,0,0)) { |
| 2233 | diagnostics_relay_client_t diag = NULL; | 2237 | diagnostics_relay_client_t diag = NULL; |
| 2234 | if (diagnostics_relay_client_start_service(device, &diag, TOOL_NAME) == DIAGNOSTICS_RELAY_E_SUCCESS) { | 2238 | if (diagnostics_relay_client_start_service(device, &diag, TOOL_NAME) == DIAGNOSTICS_RELAY_E_SUCCESS) { |
| 2235 | plist_t dict = NULL; | 2239 | plist_t dict = NULL; |
| @@ -2307,7 +2311,7 @@ checkpoint: | |||
| 2307 | /* device wants to know how much disk space is available on the computer */ | 2311 | /* device wants to know how much disk space is available on the computer */ |
| 2308 | uint64_t freespace = 0; | 2312 | uint64_t freespace = 0; |
| 2309 | int res = -1; | 2313 | int res = -1; |
| 2310 | #ifdef WIN32 | 2314 | #ifdef _WIN32 |
| 2311 | if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) { | 2315 | if (GetDiskFreeSpaceEx(backup_directory, (PULARGE_INTEGER)&freespace, NULL, NULL)) { |
| 2312 | res = 0; | 2316 | res = 0; |
| 2313 | } | 2317 | } |
| @@ -2316,7 +2320,7 @@ checkpoint: | |||
| 2316 | memset(&fs, '\0', sizeof(fs)); | 2320 | memset(&fs, '\0', sizeof(fs)); |
| 2317 | res = statvfs(backup_directory, &fs); | 2321 | res = statvfs(backup_directory, &fs); |
| 2318 | if (res == 0) { | 2322 | if (res == 0) { |
| 2319 | freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_bsize; | 2323 | freespace = (uint64_t)fs.f_bavail * (uint64_t)fs.f_frsize; |
| 2320 | } | 2324 | } |
| 2321 | #endif | 2325 | #endif |
| 2322 | plist_t freespace_item = plist_new_uint(freespace); | 2326 | plist_t freespace_item = plist_new_uint(freespace); |
diff --git a/tools/idevicebtlogger.c b/tools/idevicebtlogger.c index 8de6b22..ca68b59 100644 --- a/tools/idevicebtlogger.c +++ b/tools/idevicebtlogger.c | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | #include <assert.h> | 36 | #include <assert.h> |
| 37 | #include <fcntl.h> | 37 | #include <fcntl.h> |
| 38 | 38 | ||
| 39 | #ifdef WIN32 | 39 | #ifdef _WIN32 |
| 40 | #include <windows.h> | 40 | #include <windows.h> |
| 41 | #define sleep(x) Sleep(x*1000) | 41 | #define sleep(x) Sleep(x*1000) |
| 42 | #else | 42 | #else |
| @@ -334,7 +334,7 @@ int main(int argc, char *argv[]) | |||
| 334 | 334 | ||
| 335 | signal(SIGINT, clean_exit); | 335 | signal(SIGINT, clean_exit); |
| 336 | signal(SIGTERM, clean_exit); | 336 | signal(SIGTERM, clean_exit); |
| 337 | #ifndef WIN32 | 337 | #ifndef _WIN32 |
| 338 | signal(SIGQUIT, clean_exit); | 338 | signal(SIGQUIT, clean_exit); |
| 339 | signal(SIGPIPE, SIG_IGN); | 339 | signal(SIGPIPE, SIG_IGN); |
| 340 | #endif | 340 | #endif |
diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c index 09bd537..b9869ae 100644 --- a/tools/idevicecrashreport.c +++ b/tools/idevicecrashreport.c | |||
| @@ -31,7 +31,8 @@ | |||
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <unistd.h> | 32 | #include <unistd.h> |
| 33 | #include <getopt.h> | 33 | #include <getopt.h> |
| 34 | #ifndef WIN32 | 34 | #include <sys/stat.h> |
| 35 | #ifndef _WIN32 | ||
| 35 | #include <signal.h> | 36 | #include <signal.h> |
| 36 | #endif | 37 | #endif |
| 37 | #include <libimobiledevice-glue/utils.h> | 38 | #include <libimobiledevice-glue/utils.h> |
| @@ -42,7 +43,7 @@ | |||
| 42 | #include <libimobiledevice/afc.h> | 43 | #include <libimobiledevice/afc.h> |
| 43 | #include <plist/plist.h> | 44 | #include <plist/plist.h> |
| 44 | 45 | ||
| 45 | #ifdef WIN32 | 46 | #ifdef _WIN32 |
| 46 | #include <windows.h> | 47 | #include <windows.h> |
| 47 | #define S_IFLNK S_IFREG | 48 | #define S_IFLNK S_IFREG |
| 48 | #define S_IFSOCK S_IFREG | 49 | #define S_IFSOCK S_IFREG |
| @@ -54,11 +55,12 @@ | |||
| 54 | const char* target_directory = NULL; | 55 | const char* target_directory = NULL; |
| 55 | static int extract_raw_crash_reports = 0; | 56 | static int extract_raw_crash_reports = 0; |
| 56 | static int keep_crash_reports = 0; | 57 | static int keep_crash_reports = 0; |
| 58 | static int remove_all = 0; | ||
| 57 | 59 | ||
| 58 | static int file_exists(const char* path) | 60 | static int file_exists(const char* path) |
| 59 | { | 61 | { |
| 60 | struct stat tst; | 62 | struct stat tst; |
| 61 | #ifdef WIN32 | 63 | #ifdef _WIN32 |
| 62 | return (stat(path, &tst) == 0); | 64 | return (stat(path, &tst) == 0); |
| 63 | #else | 65 | #else |
| 64 | return (lstat(path, &tst) == 0); | 66 | return (lstat(path, &tst) == 0); |
| @@ -144,7 +146,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char | |||
| 144 | continue; | 146 | continue; |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 147 | char **fileinfo = NULL; | 149 | plist_t fileinfo = NULL; |
| 148 | struct stat stbuf; | 150 | struct stat stbuf; |
| 149 | memset(&stbuf, '\0', sizeof(struct stat)); | 151 | memset(&stbuf, '\0', sizeof(struct stat)); |
| 150 | 152 | ||
| @@ -152,7 +154,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char | |||
| 152 | strcpy(((char*)source_filename) + device_directory_length, list[k]); | 154 | strcpy(((char*)source_filename) + device_directory_length, list[k]); |
| 153 | 155 | ||
| 154 | /* assemble absolute target filename */ | 156 | /* assemble absolute target filename */ |
| 155 | #ifdef WIN32 | 157 | #ifdef _WIN32 |
| 156 | /* replace every ':' with '-' since ':' is an illegal character for file names in windows */ | 158 | /* replace every ':' with '-' since ':' is an illegal character for file names in windows */ |
| 157 | char* current_pos = strchr(list[k], ':'); | 159 | char* current_pos = strchr(list[k], ':'); |
| 158 | while (current_pos) { | 160 | while (current_pos) { |
| @@ -171,88 +173,93 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char | |||
| 171 | } | 173 | } |
| 172 | 174 | ||
| 173 | /* get file information */ | 175 | /* get file information */ |
| 174 | afc_get_file_info(afc, source_filename, &fileinfo); | 176 | afc_get_file_info_plist(afc, source_filename, &fileinfo); |
| 175 | if (!fileinfo) { | 177 | if (!fileinfo) { |
| 176 | printf("Failed to read information for '%s'. Skipping...\n", source_filename); | 178 | printf("Failed to read information for '%s'. Skipping...\n", source_filename); |
| 177 | continue; | 179 | continue; |
| 178 | } | 180 | } |
| 179 | 181 | ||
| 180 | /* parse file information */ | 182 | /* parse file information */ |
| 181 | int i; | 183 | stbuf.st_size = plist_dict_get_uint(fileinfo, "st_size"); |
| 182 | for (i = 0; fileinfo[i]; i+=2) { | 184 | const char* s_ifmt = plist_get_string_ptr(plist_dict_get_item(fileinfo, "st_ifmt"), NULL); |
| 183 | if (!strcmp(fileinfo[i], "st_size")) { | 185 | if (s_ifmt) { |
| 184 | stbuf.st_size = atoll(fileinfo[i+1]); | 186 | if (!strcmp(s_ifmt, "S_IFREG")) { |
| 185 | } else if (!strcmp(fileinfo[i], "st_ifmt")) { | 187 | stbuf.st_mode = S_IFREG; |
| 186 | if (!strcmp(fileinfo[i+1], "S_IFREG")) { | 188 | } else if (!strcmp(s_ifmt, "S_IFDIR")) { |
| 187 | stbuf.st_mode = S_IFREG; | 189 | stbuf.st_mode = S_IFDIR; |
| 188 | } else if (!strcmp(fileinfo[i+1], "S_IFDIR")) { | 190 | } else if (!strcmp(s_ifmt, "S_IFLNK")) { |
| 189 | stbuf.st_mode = S_IFDIR; | 191 | stbuf.st_mode = S_IFLNK; |
| 190 | } else if (!strcmp(fileinfo[i+1], "S_IFLNK")) { | 192 | } else if (!strcmp(s_ifmt, "S_IFBLK")) { |
| 191 | stbuf.st_mode = S_IFLNK; | 193 | stbuf.st_mode = S_IFBLK; |
| 192 | } else if (!strcmp(fileinfo[i+1], "S_IFBLK")) { | 194 | } else if (!strcmp(s_ifmt, "S_IFCHR")) { |
| 193 | stbuf.st_mode = S_IFBLK; | 195 | stbuf.st_mode = S_IFCHR; |
| 194 | } else if (!strcmp(fileinfo[i+1], "S_IFCHR")) { | 196 | } else if (!strcmp(s_ifmt, "S_IFIFO")) { |
| 195 | stbuf.st_mode = S_IFCHR; | 197 | stbuf.st_mode = S_IFIFO; |
| 196 | } else if (!strcmp(fileinfo[i+1], "S_IFIFO")) { | 198 | } else if (!strcmp(s_ifmt, "S_IFSOCK")) { |
| 197 | stbuf.st_mode = S_IFIFO; | 199 | stbuf.st_mode = S_IFSOCK; |
| 198 | } else if (!strcmp(fileinfo[i+1], "S_IFSOCK")) { | 200 | } |
| 199 | stbuf.st_mode = S_IFSOCK; | 201 | } |
| 200 | } | 202 | stbuf.st_nlink = plist_dict_get_uint(fileinfo, "st_nlink"); |
| 201 | } else if (!strcmp(fileinfo[i], "st_nlink")) { | 203 | stbuf.st_mtime = (time_t)(plist_dict_get_uint(fileinfo, "st_mtime") / 1000000000); |
| 202 | stbuf.st_nlink = atoi(fileinfo[i+1]); | 204 | const char* linktarget = plist_get_string_ptr(plist_dict_get_item(fileinfo, "LinkTarget"), NULL); |
| 203 | } else if (!strcmp(fileinfo[i], "st_mtime")) { | 205 | if (linktarget && !remove_all) { |
| 204 | stbuf.st_mtime = (time_t)(atoll(fileinfo[i+1]) / 1000000000); | 206 | /* report latest crash report filename */ |
| 205 | } else if (!strcmp(fileinfo[i], "LinkTarget")) { | 207 | printf("Link: %s\n", (char*)target_filename + strlen(target_directory)); |
| 206 | /* report latest crash report filename */ | 208 | |
| 207 | printf("Link: %s\n", (char*)target_filename + strlen(target_directory)); | 209 | /* remove any previous symlink */ |
| 208 | 210 | if (file_exists(target_filename)) { | |
| 209 | /* remove any previous symlink */ | 211 | remove(target_filename); |
| 210 | if (file_exists(target_filename)) { | 212 | } |
| 211 | remove(target_filename); | ||
| 212 | } | ||
| 213 | 213 | ||
| 214 | #ifndef WIN32 | 214 | #ifndef _WIN32 |
| 215 | /* use relative filename */ | 215 | /* use relative filename */ |
| 216 | char* b = strrchr(fileinfo[i+1], '/'); | 216 | const char* b = strrchr(linktarget, '/'); |
| 217 | if (b == NULL) { | 217 | if (b == NULL) { |
| 218 | b = fileinfo[i+1]; | 218 | b = linktarget; |
| 219 | } else { | 219 | } else { |
| 220 | b++; | 220 | b++; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | /* create a symlink pointing to latest log */ | 223 | /* create a symlink pointing to latest log */ |
| 224 | if (symlink(b, target_filename) < 0) { | 224 | if (symlink(b, target_filename) < 0) { |
| 225 | fprintf(stderr, "Can't create symlink to %s\n", b); | 225 | fprintf(stderr, "Can't create symlink to %s\n", b); |
| 226 | } | 226 | } |
| 227 | #endif | 227 | #endif |
| 228 | 228 | ||
| 229 | if (!keep_crash_reports) | 229 | if (!keep_crash_reports) |
| 230 | afc_remove_path(afc, source_filename); | 230 | afc_remove_path(afc, source_filename); |
| 231 | 231 | ||
| 232 | res = 0; | 232 | res = 0; |
| 233 | } | ||
| 234 | } | 233 | } |
| 235 | 234 | ||
| 236 | /* free file information */ | 235 | /* free file information */ |
| 237 | afc_dictionary_free(fileinfo); | 236 | plist_free(fileinfo); |
| 238 | 237 | ||
| 239 | /* recurse into child directories */ | 238 | /* recurse into child directories */ |
| 240 | if (S_ISDIR(stbuf.st_mode)) { | 239 | if (S_ISDIR(stbuf.st_mode)) { |
| 241 | #ifdef WIN32 | 240 | if (!remove_all) { |
| 242 | mkdir(target_filename); | 241 | #ifdef _WIN32 |
| 242 | mkdir(target_filename); | ||
| 243 | #else | 243 | #else |
| 244 | mkdir(target_filename, 0755); | 244 | mkdir(target_filename, 0755); |
| 245 | #endif | 245 | #endif |
| 246 | } | ||
| 246 | res = afc_client_copy_and_remove_crash_reports(afc, source_filename, target_filename, filename_filter); | 247 | res = afc_client_copy_and_remove_crash_reports(afc, source_filename, target_filename, filename_filter); |
| 247 | 248 | ||
| 248 | /* remove directory from device */ | 249 | /* remove directory from device */ |
| 249 | if (!keep_crash_reports) | 250 | if (!remove_all && !keep_crash_reports) |
| 250 | afc_remove_path(afc, source_filename); | 251 | afc_remove_path(afc, source_filename); |
| 251 | } else if (S_ISREG(stbuf.st_mode)) { | 252 | } else if (S_ISREG(stbuf.st_mode)) { |
| 252 | if (filename_filter != NULL && strstr(source_filename, filename_filter) == NULL) { | 253 | if (filename_filter != NULL && strstr(source_filename, filename_filter) == NULL) { |
| 253 | continue; | 254 | continue; |
| 254 | } | 255 | } |
| 255 | 256 | ||
| 257 | if (remove_all) { | ||
| 258 | printf("Remove: %s\n", source_filename); | ||
| 259 | afc_remove_path(afc, source_filename); | ||
| 260 | continue; | ||
| 261 | } | ||
| 262 | |||
| 256 | /* copy file to host */ | 263 | /* copy file to host */ |
| 257 | afc_error = afc_file_open(afc, source_filename, AFC_FOPEN_RDONLY, &handle); | 264 | afc_error = afc_file_open(afc, source_filename, AFC_FOPEN_RDONLY, &handle); |
| 258 | if(afc_error != AFC_E_SUCCESS) { | 265 | if(afc_error != AFC_E_SUCCESS) { |
| @@ -331,6 +338,7 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 331 | " -f, --filter NAME filter crash reports by NAME (case sensitive)\n" | 338 | " -f, --filter NAME filter crash reports by NAME (case sensitive)\n" |
| 332 | " -h, --help prints usage information\n" | 339 | " -h, --help prints usage information\n" |
| 333 | " -v, --version prints version information\n" | 340 | " -v, --version prints version information\n" |
| 341 | " --remove-all remove all crash logs found\n" | ||
| 334 | "\n" | 342 | "\n" |
| 335 | "Homepage: <" PACKAGE_URL ">\n" | 343 | "Homepage: <" PACKAGE_URL ">\n" |
| 336 | "Bug Reports: <" PACKAGE_BUGREPORT ">\n" | 344 | "Bug Reports: <" PACKAGE_BUGREPORT ">\n" |
| @@ -361,10 +369,11 @@ int main(int argc, char* argv[]) | |||
| 361 | { "filter", required_argument, NULL, 'f' }, | 369 | { "filter", required_argument, NULL, 'f' }, |
| 362 | { "extract", no_argument, NULL, 'e' }, | 370 | { "extract", no_argument, NULL, 'e' }, |
| 363 | { "keep", no_argument, NULL, 'k' }, | 371 | { "keep", no_argument, NULL, 'k' }, |
| 372 | { "remove-all", no_argument, NULL, 1 }, | ||
| 364 | { NULL, 0, NULL, 0} | 373 | { NULL, 0, NULL, 0} |
| 365 | }; | 374 | }; |
| 366 | 375 | ||
| 367 | #ifndef WIN32 | 376 | #ifndef _WIN32 |
| 368 | signal(SIGPIPE, SIG_IGN); | 377 | signal(SIGPIPE, SIG_IGN); |
| 369 | #endif | 378 | #endif |
| 370 | 379 | ||
| @@ -405,6 +414,9 @@ int main(int argc, char* argv[]) | |||
| 405 | case 'k': | 414 | case 'k': |
| 406 | keep_crash_reports = 1; | 415 | keep_crash_reports = 1; |
| 407 | break; | 416 | break; |
| 417 | case 1: | ||
| 418 | remove_all = 1; | ||
| 419 | break; | ||
| 408 | default: | 420 | default: |
| 409 | print_usage(argc, argv, 1); | 421 | print_usage(argc, argv, 1); |
| 410 | return 2; | 422 | return 2; |
| @@ -414,12 +426,16 @@ int main(int argc, char* argv[]) | |||
| 414 | argv += optind; | 426 | argv += optind; |
| 415 | 427 | ||
| 416 | /* ensure a target directory was supplied */ | 428 | /* ensure a target directory was supplied */ |
| 417 | if (!argv[0]) { | 429 | if (!remove_all) { |
| 418 | fprintf(stderr, "ERROR: missing target directory.\n"); | 430 | if (!argv[0]) { |
| 419 | print_usage(argc+optind, argv-optind, 1); | 431 | fprintf(stderr, "ERROR: missing target directory.\n"); |
| 420 | return 2; | 432 | print_usage(argc+optind, argv-optind, 1); |
| 433 | return 2; | ||
| 434 | } | ||
| 435 | target_directory = argv[0]; | ||
| 436 | } else { | ||
| 437 | target_directory = "."; | ||
| 421 | } | 438 | } |
| 422 | target_directory = argv[0]; | ||
| 423 | 439 | ||
| 424 | /* check if target directory exists */ | 440 | /* check if target directory exists */ |
| 425 | if (!file_exists(target_directory)) { | 441 | if (!file_exists(target_directory)) { |
diff --git a/tools/idevicedate.c b/tools/idevicedate.c index d05f63e..31b0cf7 100644 --- a/tools/idevicedate.c +++ b/tools/idevicedate.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #if HAVE_LANGINFO_CODESET | 33 | #if HAVE_LANGINFO_CODESET |
| 34 | #include <langinfo.h> | 34 | #include <langinfo.h> |
| 35 | #endif | 35 | #endif |
| 36 | #ifndef WIN32 | 36 | #ifndef _WIN32 |
| 37 | #include <signal.h> | 37 | #include <signal.h> |
| 38 | #endif | 38 | #endif |
| 39 | 39 | ||
| @@ -43,7 +43,7 @@ | |||
| 43 | #ifdef _DATE_FMT | 43 | #ifdef _DATE_FMT |
| 44 | #define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT) | 44 | #define DATE_FMT_LANGINFO nl_langinfo (_DATE_FMT) |
| 45 | #else | 45 | #else |
| 46 | #ifdef WIN32 | 46 | #ifdef _WIN32 |
| 47 | #define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y" | 47 | #define DATE_FMT_LANGINFO "%a %b %#d %H:%M:%S %Z %Y" |
| 48 | #else | 48 | #else |
| 49 | #define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y" | 49 | #define DATE_FMT_LANGINFO "%a %b %e %H:%M:%S %Z %Y" |
| @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) | |||
| 104 | { NULL, 0, NULL, 0} | 104 | { NULL, 0, NULL, 0} |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | #ifndef WIN32 | 107 | #ifndef _WIN32 |
| 108 | signal(SIGPIPE, SIG_IGN); | 108 | signal(SIGPIPE, SIG_IGN); |
| 109 | #endif | 109 | #endif |
| 110 | /* parse cmdline args */ | 110 | /* parse cmdline args */ |
diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c index 36c594e..3f2e289 100644 --- a/tools/idevicedebug.c +++ b/tools/idevicedebug.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #include <libgen.h> | 34 | #include <libgen.h> |
| 35 | #include <getopt.h> | 35 | #include <getopt.h> |
| 36 | 36 | ||
| 37 | #ifdef WIN32 | 37 | #ifdef _WIN32 |
| 38 | #include <windows.h> | 38 | #include <windows.h> |
| 39 | #define sleep(x) Sleep(x*1000) | 39 | #define sleep(x) Sleep(x*1000) |
| 40 | #endif | 40 | #endif |
| @@ -239,7 +239,7 @@ int main(int argc, char *argv[]) | |||
| 239 | /* map signals */ | 239 | /* map signals */ |
| 240 | signal(SIGINT, on_signal); | 240 | signal(SIGINT, on_signal); |
| 241 | signal(SIGTERM, on_signal); | 241 | signal(SIGTERM, on_signal); |
| 242 | #ifndef WIN32 | 242 | #ifndef _WIN32 |
| 243 | signal(SIGQUIT, on_signal); | 243 | signal(SIGQUIT, on_signal); |
| 244 | signal(SIGPIPE, SIG_IGN); | 244 | signal(SIGPIPE, SIG_IGN); |
| 245 | #endif | 245 | #endif |
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c index 9fe7051..fb082b3 100644 --- a/tools/idevicedebugserverproxy.c +++ b/tools/idevicedebugserverproxy.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <getopt.h> | 32 | #include <getopt.h> |
| 33 | #include <errno.h> | 33 | #include <errno.h> |
| 34 | #include <signal.h> | 34 | #include <signal.h> |
| 35 | #ifdef WIN32 | 35 | #ifdef _WIN32 |
| 36 | #include <winsock2.h> | 36 | #include <winsock2.h> |
| 37 | #include <windows.h> | 37 | #include <windows.h> |
| 38 | #else | 38 | #else |
| @@ -219,7 +219,7 @@ int main(int argc, char *argv[]) | |||
| 219 | { NULL, 0, NULL, 0} | 219 | { NULL, 0, NULL, 0} |
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | #ifndef WIN32 | 222 | #ifndef _WIN32 |
| 223 | struct sigaction sa; | 223 | struct sigaction sa; |
| 224 | struct sigaction si; | 224 | struct sigaction si; |
| 225 | memset(&sa, '\0', sizeof(struct sigaction)); | 225 | memset(&sa, '\0', sizeof(struct sigaction)); |
diff --git a/tools/idevicedevmodectl.c b/tools/idevicedevmodectl.c index bd1de6a..6bf1a1c 100644 --- a/tools/idevicedevmodectl.c +++ b/tools/idevicedevmodectl.c | |||
| @@ -32,11 +32,11 @@ | |||
| 32 | #include <sys/stat.h> | 32 | #include <sys/stat.h> |
| 33 | #include <unistd.h> | 33 | #include <unistd.h> |
| 34 | #include <errno.h> | 34 | #include <errno.h> |
| 35 | #ifndef WIN32 | 35 | #ifndef _WIN32 |
| 36 | #include <signal.h> | 36 | #include <signal.h> |
| 37 | #endif | 37 | #endif |
| 38 | 38 | ||
| 39 | #ifdef WIN32 | 39 | #ifdef _WIN32 |
| 40 | #include <windows.h> | 40 | #include <windows.h> |
| 41 | #define __usleep(x) Sleep(x/1000) | 41 | #define __usleep(x) Sleep(x/1000) |
| 42 | #else | 42 | #else |
| @@ -259,7 +259,7 @@ int main(int argc, char *argv[]) | |||
| 259 | { NULL, 0, NULL, 0} | 259 | { NULL, 0, NULL, 0} |
| 260 | }; | 260 | }; |
| 261 | 261 | ||
| 262 | #ifndef WIN32 | 262 | #ifndef _WIN32 |
| 263 | signal(SIGPIPE, SIG_IGN); | 263 | signal(SIGPIPE, SIG_IGN); |
| 264 | #endif | 264 | #endif |
| 265 | /* parse cmdline args */ | 265 | /* parse cmdline args */ |
diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c index e699bc4..365c0a4 100644 --- a/tools/idevicediagnostics.c +++ b/tools/idevicediagnostics.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <getopt.h> | 31 | #include <getopt.h> |
| 32 | #include <errno.h> | 32 | #include <errno.h> |
| 33 | #include <time.h> | 33 | #include <time.h> |
| 34 | #ifndef WIN32 | 34 | #ifndef _WIN32 |
| 35 | #include <signal.h> | 35 | #include <signal.h> |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| @@ -113,7 +113,7 @@ int main(int argc, char **argv) | |||
| 113 | { NULL, 0, NULL, 0} | 113 | { NULL, 0, NULL, 0} |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
| 116 | #ifndef WIN32 | 116 | #ifndef _WIN32 |
| 117 | signal(SIGPIPE, SIG_IGN); | 117 | signal(SIGPIPE, SIG_IGN); |
| 118 | #endif | 118 | #endif |
| 119 | /* parse cmdline args */ | 119 | /* parse cmdline args */ |
diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c index 29cc5c9..65eb882 100644 --- a/tools/ideviceenterrecovery.c +++ b/tools/ideviceenterrecovery.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <stdlib.h> | 30 | #include <stdlib.h> |
| 31 | #include <getopt.h> | 31 | #include <getopt.h> |
| 32 | #include <errno.h> | 32 | #include <errno.h> |
| 33 | #ifndef WIN32 | 33 | #ifndef _WIN32 |
| 34 | #include <signal.h> | 34 | #include <signal.h> |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) | |||
| 70 | { NULL, 0, NULL, 0} | 70 | { NULL, 0, NULL, 0} |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | #ifndef WIN32 | 73 | #ifndef _WIN32 |
| 74 | signal(SIGPIPE, SIG_IGN); | 74 | signal(SIGPIPE, SIG_IGN); |
| 75 | #endif | 75 | #endif |
| 76 | /* parse cmdline args */ | 76 | /* parse cmdline args */ |
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c index 511583e..b319d05 100644 --- a/tools/ideviceimagemounter.c +++ b/tools/ideviceimagemounter.c | |||
| @@ -36,7 +36,8 @@ | |||
| 36 | #include <time.h> | 36 | #include <time.h> |
| 37 | #include <sys/time.h> | 37 | #include <sys/time.h> |
| 38 | #include <inttypes.h> | 38 | #include <inttypes.h> |
| 39 | #ifndef WIN32 | 39 | #include <sys/stat.h> |
| 40 | #ifndef _WIN32 | ||
| 40 | #include <signal.h> | 41 | #include <signal.h> |
| 41 | #endif | 42 | #endif |
| 42 | 43 | ||
| @@ -87,7 +88,7 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 87 | " mount PATH Mount the developer disk image at PATH.\n" | 88 | " mount PATH Mount the developer disk image at PATH.\n" |
| 88 | " For iOS 17+, PATH is a directory containing a .dmg image,\n" | 89 | " For iOS 17+, PATH is a directory containing a .dmg image,\n" |
| 89 | " a BuildManifest.plist, and a Firmware sub-directory;\n" | 90 | " a BuildManifest.plist, and a Firmware sub-directory;\n" |
| 90 | " for older versions PATH is a .dmg filename with a" | 91 | " for older versions PATH is a .dmg filename with a\n" |
| 91 | " .dmg.signature in the same directory, or with another\n" | 92 | " .dmg.signature in the same directory, or with another\n" |
| 92 | " parameter pointing to a file elsewhere.\n" | 93 | " parameter pointing to a file elsewhere.\n" |
| 93 | " list List mounted disk images.\n" | 94 | " list List mounted disk images.\n" |
| @@ -183,7 +184,7 @@ int main(int argc, char **argv) | |||
| 183 | size_t image_size = 0; | 184 | size_t image_size = 0; |
| 184 | char *image_sig_path = NULL; | 185 | char *image_sig_path = NULL; |
| 185 | 186 | ||
| 186 | #ifndef WIN32 | 187 | #ifndef _WIN32 |
| 187 | signal(SIGPIPE, SIG_IGN); | 188 | signal(SIGPIPE, SIG_IGN); |
| 188 | #endif | 189 | #endif |
| 189 | parse_opts(argc, argv); | 190 | parse_opts(argc, argv); |
| @@ -267,23 +268,14 @@ int main(int argc, char **argv) | |||
| 267 | goto leave; | 268 | goto leave; |
| 268 | } | 269 | } |
| 269 | 270 | ||
| 270 | plist_t pver = NULL; | 271 | unsigned int device_version = idevice_get_device_version(device); |
| 271 | char *product_version = NULL; | 272 | |
| 272 | lockdownd_get_value(lckd, NULL, "ProductVersion", &pver); | ||
| 273 | if (pver && plist_get_node_type(pver) == PLIST_STRING) { | ||
| 274 | plist_get_string_val(pver, &product_version); | ||
| 275 | } | ||
| 276 | disk_image_upload_type_t disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_AFC; | 273 | disk_image_upload_type_t disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_AFC; |
| 277 | int product_version_major = 0; | 274 | if (device_version >= IDEVICE_DEVICE_VERSION(7,0,0)) { |
| 278 | int product_version_minor = 0; | 275 | disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE; |
| 279 | if (product_version) { | ||
| 280 | if (sscanf(product_version, "%d.%d.%*d", &product_version_major, &product_version_minor) == 2) { | ||
| 281 | if (product_version_major >= 7) | ||
| 282 | disk_image_upload_type = DISK_IMAGE_UPLOAD_TYPE_UPLOAD_IMAGE; | ||
| 283 | } | ||
| 284 | } | 276 | } |
| 285 | 277 | ||
| 286 | if (product_version_major >= 16) { | 278 | if (device_version >= IDEVICE_DEVICE_VERSION(16,0,0)) { |
| 287 | uint8_t dev_mode_status = 0; | 279 | uint8_t dev_mode_status = 0; |
| 288 | plist_t val = NULL; | 280 | plist_t val = NULL; |
| 289 | ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); | 281 | ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); |
| @@ -336,7 +328,7 @@ int main(int argc, char **argv) | |||
| 336 | goto leave; | 328 | goto leave; |
| 337 | } | 329 | } |
| 338 | image_size = fst.st_size; | 330 | image_size = fst.st_size; |
| 339 | if (product_version_major < 17 && stat(image_sig_path, &fst) != 0) { | 331 | if (device_version < IDEVICE_DEVICE_VERSION(17,0,0) && stat(image_sig_path, &fst) != 0) { |
| 340 | fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno)); | 332 | fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno)); |
| 341 | goto leave; | 333 | goto leave; |
| 342 | } | 334 | } |
| @@ -351,7 +343,7 @@ int main(int argc, char **argv) | |||
| 351 | if (cmd == CMD_LIST) { | 343 | if (cmd == CMD_LIST) { |
| 352 | /* list mounts mode */ | 344 | /* list mounts mode */ |
| 353 | if (!imagetype) { | 345 | if (!imagetype) { |
| 354 | if (product_version_major < 17) { | 346 | if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) { |
| 355 | imagetype = "Developer"; | 347 | imagetype = "Developer"; |
| 356 | } else { | 348 | } else { |
| 357 | imagetype = "Personalized"; | 349 | imagetype = "Personalized"; |
| @@ -371,7 +363,7 @@ int main(int argc, char **argv) | |||
| 371 | struct stat fst; | 363 | struct stat fst; |
| 372 | plist_t mount_options = NULL; | 364 | plist_t mount_options = NULL; |
| 373 | 365 | ||
| 374 | if (product_version_major < 17) { | 366 | if (device_version < IDEVICE_DEVICE_VERSION(17,0,0)) { |
| 375 | f = fopen(image_sig_path, "rb"); | 367 | f = fopen(image_sig_path, "rb"); |
| 376 | if (!f) { | 368 | if (!f) { |
| 377 | fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno)); | 369 | fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno)); |
| @@ -606,20 +598,13 @@ int main(int argc, char **argv) | |||
| 606 | case DISK_IMAGE_UPLOAD_TYPE_AFC: | 598 | case DISK_IMAGE_UPLOAD_TYPE_AFC: |
| 607 | default: | 599 | default: |
| 608 | printf("Uploading %s --> afc:///%s\n", image_path, targetname); | 600 | printf("Uploading %s --> afc:///%s\n", image_path, targetname); |
| 609 | char **strs = NULL; | 601 | plist_t fileinfo = NULL; |
| 610 | if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { | 602 | if (afc_get_file_info_plist(afc, PKG_PATH, &fileinfo) != AFC_E_SUCCESS) { |
| 611 | if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { | 603 | if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { |
| 612 | fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); | 604 | fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); |
| 613 | } | 605 | } |
| 614 | } | 606 | } |
| 615 | if (strs) { | 607 | plist_free(fileinfo); |
| 616 | int i = 0; | ||
| 617 | while (strs[i]) { | ||
| 618 | free(strs[i]); | ||
| 619 | i++; | ||
| 620 | } | ||
| 621 | free(strs); | ||
| 622 | } | ||
| 623 | 608 | ||
| 624 | uint64_t af = 0; | 609 | uint64_t af = 0; |
| 625 | if ((afc_file_open(afc, targetname, AFC_FOPEN_WRONLY, &af) != | 610 | if ((afc_file_open(afc, targetname, AFC_FOPEN_WRONLY, &af) != |
diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c index fd45763..20cc916 100644 --- a/tools/ideviceinfo.c +++ b/tools/ideviceinfo.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <errno.h> | 31 | #include <errno.h> |
| 32 | #include <stdlib.h> | 32 | #include <stdlib.h> |
| 33 | #include <getopt.h> | 33 | #include <getopt.h> |
| 34 | #ifndef WIN32 | 34 | #ifndef _WIN32 |
| 35 | #include <signal.h> | 35 | #include <signal.h> |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) | |||
| 152 | { NULL, 0, NULL, 0} | 152 | { NULL, 0, NULL, 0} |
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | #ifndef WIN32 | 155 | #ifndef _WIN32 |
| 156 | signal(SIGPIPE, SIG_IGN); | 156 | signal(SIGPIPE, SIG_IGN); |
| 157 | #endif | 157 | #endif |
| 158 | 158 | ||
diff --git a/tools/idevicename.c b/tools/idevicename.c index 69b76f6..248bda3 100644 --- a/tools/idevicename.c +++ b/tools/idevicename.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <unistd.h> | 30 | #include <unistd.h> |
| 31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
| 32 | #include <getopt.h> | 32 | #include <getopt.h> |
| 33 | #ifndef WIN32 | 33 | #ifndef _WIN32 |
| 34 | #include <signal.h> | 34 | #include <signal.h> |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| @@ -72,7 +72,7 @@ int main(int argc, char** argv) | |||
| 72 | const char* udid = NULL; | 72 | const char* udid = NULL; |
| 73 | int use_network = 0; | 73 | int use_network = 0; |
| 74 | 74 | ||
| 75 | #ifndef WIN32 | 75 | #ifndef _WIN32 |
| 76 | signal(SIGPIPE, SIG_IGN); | 76 | signal(SIGPIPE, SIG_IGN); |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c index d1e25c1..192192a 100644 --- a/tools/idevicenotificationproxy.c +++ b/tools/idevicenotificationproxy.c | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | * idevicenotificationproxy.c | 2 | * idevicenotificationproxy.c |
| 3 | * Simple client for the notification_proxy service | 3 | * Simple client for the notification_proxy service |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved. | 5 | * Copyright (c) 2018-2024 Nikias Bassen, All Rights Reserved. |
| 6 | * Copyright (c) 2009-2015 Martin Szulecki, All Rights Reserved. | ||
| 6 | * | 7 | * |
| 7 | * This library is free software; you can redistribute it and/or | 8 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public | 9 | * modify it under the terms of the GNU Lesser General Public |
| @@ -32,7 +33,7 @@ | |||
| 32 | #include <errno.h> | 33 | #include <errno.h> |
| 33 | #include <signal.h> | 34 | #include <signal.h> |
| 34 | 35 | ||
| 35 | #ifdef WIN32 | 36 | #ifdef _WIN32 |
| 36 | #include <windows.h> | 37 | #include <windows.h> |
| 37 | #define sleep(x) Sleep(x*1000) | 38 | #define sleep(x) Sleep(x*1000) |
| 38 | #else | 39 | #else |
| @@ -75,6 +76,7 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 75 | "\n" | 76 | "\n" |
| 76 | "The following OPTIONS are accepted:\n" | 77 | "The following OPTIONS are accepted:\n" |
| 77 | " -u, --udid UDID target specific device by UDID\n" | 78 | " -u, --udid UDID target specific device by UDID\n" |
| 79 | " -i, --insecure use insecure notification proxy (non-paired device)\n" | ||
| 78 | " -n, --network connect to network device\n" | 80 | " -n, --network connect to network device\n" |
| 79 | " -d, --debug enable communication debugging\n" | 81 | " -d, --debug enable communication debugging\n" |
| 80 | " -h, --help prints usage information\n" | 82 | " -h, --help prints usage information\n" |
| @@ -102,6 +104,7 @@ int main(int argc, char *argv[]) | |||
| 102 | int i = 0; | 104 | int i = 0; |
| 103 | const char* udid = NULL; | 105 | const char* udid = NULL; |
| 104 | int use_network = 0; | 106 | int use_network = 0; |
| 107 | int insecure = 0; | ||
| 105 | int cmd = CMD_NONE; | 108 | int cmd = CMD_NONE; |
| 106 | char* cmd_arg = NULL; | 109 | char* cmd_arg = NULL; |
| 107 | 110 | ||
| @@ -114,6 +117,7 @@ int main(int argc, char *argv[]) | |||
| 114 | { "debug", no_argument, NULL, 'd' }, | 117 | { "debug", no_argument, NULL, 'd' }, |
| 115 | { "help", no_argument, NULL, 'h' }, | 118 | { "help", no_argument, NULL, 'h' }, |
| 116 | { "udid", required_argument, NULL, 'u' }, | 119 | { "udid", required_argument, NULL, 'u' }, |
| 120 | { "insecure", no_argument, NULL, 'i' }, | ||
| 117 | { "network", no_argument, NULL, 'n' }, | 121 | { "network", no_argument, NULL, 'n' }, |
| 118 | { "version", no_argument, NULL, 'v' }, | 122 | { "version", no_argument, NULL, 'v' }, |
| 119 | { NULL, 0, NULL, 0} | 123 | { NULL, 0, NULL, 0} |
| @@ -121,13 +125,13 @@ int main(int argc, char *argv[]) | |||
| 121 | 125 | ||
| 122 | signal(SIGINT, clean_exit); | 126 | signal(SIGINT, clean_exit); |
| 123 | signal(SIGTERM, clean_exit); | 127 | signal(SIGTERM, clean_exit); |
| 124 | #ifndef WIN32 | 128 | #ifndef _WIN32 |
| 125 | signal(SIGQUIT, clean_exit); | 129 | signal(SIGQUIT, clean_exit); |
| 126 | signal(SIGPIPE, SIG_IGN); | 130 | signal(SIGPIPE, SIG_IGN); |
| 127 | #endif | 131 | #endif |
| 128 | 132 | ||
| 129 | /* parse cmdline args */ | 133 | /* parse cmdline args */ |
| 130 | while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) { | 134 | while ((c = getopt_long(argc, argv, "dhu:inv", longopts, NULL)) != -1) { |
| 131 | switch (c) { | 135 | switch (c) { |
| 132 | case 'd': | 136 | case 'd': |
| 133 | idevice_set_debug_level(1); | 137 | idevice_set_debug_level(1); |
| @@ -143,6 +147,9 @@ int main(int argc, char *argv[]) | |||
| 143 | case 'n': | 147 | case 'n': |
| 144 | use_network = 1; | 148 | use_network = 1; |
| 145 | break; | 149 | break; |
| 150 | case 'i': | ||
| 151 | insecure = 1; | ||
| 152 | break; | ||
| 146 | case 'h': | 153 | case 'h': |
| 147 | print_usage(argc, argv, 0); | 154 | print_usage(argc, argv, 0); |
| 148 | return 0; | 155 | return 0; |
| @@ -214,12 +221,17 @@ int main(int argc, char *argv[]) | |||
| 214 | goto cleanup; | 221 | goto cleanup; |
| 215 | } | 222 | } |
| 216 | 223 | ||
| 217 | if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME))) { | 224 | if (insecure) { |
| 218 | fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ret); | 225 | ret = lockdownd_client_new(device, &client, TOOL_NAME); |
| 226 | } else { | ||
| 227 | ret = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME); | ||
| 228 | } | ||
| 229 | if (LOCKDOWN_E_SUCCESS != ret) { | ||
| 230 | fprintf(stderr, "ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ret), ret); | ||
| 219 | goto cleanup; | 231 | goto cleanup; |
| 220 | } | 232 | } |
| 221 | 233 | ||
| 222 | ret = lockdownd_start_service(client, NP_SERVICE_NAME, &service); | 234 | ret = lockdownd_start_service(client, (insecure) ? "com.apple.mobile.insecure_notification_proxy" : NP_SERVICE_NAME, &service); |
| 223 | 235 | ||
| 224 | lockdownd_client_free(client); | 236 | lockdownd_client_free(client); |
| 225 | 237 | ||
diff --git a/tools/idevicepair.c b/tools/idevicepair.c index 94d3f04..884c690 100644 --- a/tools/idevicepair.c +++ b/tools/idevicepair.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <getopt.h> | 32 | #include <getopt.h> |
| 33 | #include <ctype.h> | 33 | #include <ctype.h> |
| 34 | #include <unistd.h> | 34 | #include <unistd.h> |
| 35 | #ifdef WIN32 | 35 | #ifdef _WIN32 |
| 36 | #include <windows.h> | 36 | #include <windows.h> |
| 37 | #include <conio.h> | 37 | #include <conio.h> |
| 38 | #else | 38 | #else |
| @@ -50,7 +50,7 @@ static char *udid = NULL; | |||
| 50 | 50 | ||
| 51 | #ifdef HAVE_WIRELESS_PAIRING | 51 | #ifdef HAVE_WIRELESS_PAIRING |
| 52 | 52 | ||
| 53 | #ifdef WIN32 | 53 | #ifdef _WIN32 |
| 54 | #define BS_CC '\b' | 54 | #define BS_CC '\b' |
| 55 | #define my_getch getch | 55 | #define my_getch getch |
| 56 | #else | 56 | #else |
| @@ -293,7 +293,7 @@ int main(int argc, char **argv) | |||
| 293 | } | 293 | } |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | #ifndef WIN32 | 296 | #ifndef _WIN32 |
| 297 | signal(SIGPIPE, SIG_IGN); | 297 | signal(SIGPIPE, SIG_IGN); |
| 298 | #endif | 298 | #endif |
| 299 | 299 | ||
diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c index 4080a28..94f4ec5 100644 --- a/tools/ideviceprovision.c +++ b/tools/ideviceprovision.c | |||
| @@ -32,11 +32,12 @@ | |||
| 32 | #include <getopt.h> | 32 | #include <getopt.h> |
| 33 | #include <sys/stat.h> | 33 | #include <sys/stat.h> |
| 34 | #include <errno.h> | 34 | #include <errno.h> |
| 35 | #ifndef WIN32 | 35 | #ifndef _WIN32 |
| 36 | #include <signal.h> | 36 | #include <signal.h> |
| 37 | #endif | 37 | #endif |
| 38 | 38 | ||
| 39 | #ifdef WIN32 | 39 | #ifdef _WIN32 |
| 40 | #include <winsock2.h> | ||
| 40 | #include <windows.h> | 41 | #include <windows.h> |
| 41 | #else | 42 | #else |
| 42 | #include <arpa/inet.h> | 43 | #include <arpa/inet.h> |
| @@ -314,7 +315,7 @@ int main(int argc, char *argv[]) | |||
| 314 | { NULL, 0, NULL, 0} | 315 | { NULL, 0, NULL, 0} |
| 315 | }; | 316 | }; |
| 316 | 317 | ||
| 317 | #ifndef WIN32 | 318 | #ifndef _WIN32 |
| 318 | signal(SIGPIPE, SIG_IGN); | 319 | signal(SIGPIPE, SIG_IGN); |
| 319 | #endif | 320 | #endif |
| 320 | /* parse cmdline args */ | 321 | /* parse cmdline args */ |
| @@ -475,27 +476,7 @@ int main(int argc, char *argv[]) | |||
| 475 | return -1; | 476 | return -1; |
| 476 | } | 477 | } |
| 477 | 478 | ||
| 478 | plist_t pver = NULL; | 479 | unsigned int device_version = idevice_get_device_version(device); |
| 479 | char *pver_s = NULL; | ||
| 480 | lockdownd_get_value(client, NULL, "ProductVersion", &pver); | ||
| 481 | if (pver && plist_get_node_type(pver) == PLIST_STRING) { | ||
| 482 | plist_get_string_val(pver, &pver_s); | ||
| 483 | } | ||
| 484 | plist_free(pver); | ||
| 485 | int product_version_major = 0; | ||
| 486 | int product_version_minor = 0; | ||
| 487 | int product_version_patch = 0; | ||
| 488 | if (pver_s) { | ||
| 489 | sscanf(pver_s, "%d.%d.%d", &product_version_major, &product_version_minor, &product_version_patch); | ||
| 490 | free(pver_s); | ||
| 491 | } | ||
| 492 | if (product_version_major == 0) { | ||
| 493 | fprintf(stderr, "ERROR: Could not determine the device's ProductVersion\n"); | ||
| 494 | lockdownd_client_free(client); | ||
| 495 | idevice_free(device); | ||
| 496 | return -1; | ||
| 497 | } | ||
| 498 | int product_version = ((product_version_major & 0xFF) << 16) | ((product_version_minor & 0xFF) << 8) | (product_version_patch & 0xFF); | ||
| 499 | 480 | ||
| 500 | lockdownd_error_t lerr = lockdownd_start_service(client, MISAGENT_SERVICE_NAME, &service); | 481 | lockdownd_error_t lerr = lockdownd_start_service(client, MISAGENT_SERVICE_NAME, &service); |
| 501 | if (lerr != LOCKDOWN_E_SUCCESS) { | 482 | if (lerr != LOCKDOWN_E_SUCCESS) { |
| @@ -546,7 +527,7 @@ int main(int argc, char *argv[]) | |||
| 546 | { | 527 | { |
| 547 | plist_t profiles = NULL; | 528 | plist_t profiles = NULL; |
| 548 | misagent_error_t merr; | 529 | misagent_error_t merr; |
| 549 | if (product_version < 0x090300) { | 530 | if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) { |
| 550 | merr = misagent_copy(mis, &profiles); | 531 | merr = misagent_copy(mis, &profiles); |
| 551 | } else { | 532 | } else { |
| 552 | merr = misagent_copy_all(mis, &profiles); | 533 | merr = misagent_copy_all(mis, &profiles); |
| @@ -631,7 +612,7 @@ int main(int argc, char *argv[]) | |||
| 631 | /* remove all provisioning profiles */ | 612 | /* remove all provisioning profiles */ |
| 632 | plist_t profiles = NULL; | 613 | plist_t profiles = NULL; |
| 633 | misagent_error_t merr; | 614 | misagent_error_t merr; |
| 634 | if (product_version < 0x090300) { | 615 | if (device_version < IDEVICE_DEVICE_VERSION(9,3,0)) { |
| 635 | merr = misagent_copy(mis, &profiles); | 616 | merr = misagent_copy(mis, &profiles); |
| 636 | } else { | 617 | } else { |
| 637 | merr = misagent_copy_all(mis, &profiles); | 618 | merr = misagent_copy_all(mis, &profiles); |
diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c index 0e694c7..bfaa059 100644 --- a/tools/idevicescreenshot.c +++ b/tools/idevicescreenshot.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <errno.h> | 32 | #include <errno.h> |
| 33 | #include <time.h> | 33 | #include <time.h> |
| 34 | #include <unistd.h> | 34 | #include <unistd.h> |
| 35 | #ifndef WIN32 | 35 | #ifndef _WIN32 |
| 36 | #include <signal.h> | 36 | #include <signal.h> |
| 37 | #endif | 37 | #endif |
| 38 | 38 | ||
| @@ -142,7 +142,7 @@ int main(int argc, char **argv) | |||
| 142 | { NULL, 0, NULL, 0} | 142 | { NULL, 0, NULL, 0} |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | #ifndef WIN32 | 145 | #ifndef _WIN32 |
| 146 | signal(SIGPIPE, SIG_IGN); | 146 | signal(SIGPIPE, SIG_IGN); |
| 147 | #endif | 147 | #endif |
| 148 | /* parse cmdline args */ | 148 | /* parse cmdline args */ |
diff --git a/tools/idevicesetlocation.c b/tools/idevicesetlocation.c index 69fbaf5..dca8830 100644 --- a/tools/idevicesetlocation.c +++ b/tools/idevicesetlocation.c | |||
| @@ -113,7 +113,7 @@ int main(int argc, char **argv) | |||
| 113 | 113 | ||
| 114 | if ((argc > 2) || (argc < 1)) { | 114 | if ((argc > 2) || (argc < 1)) { |
| 115 | print_usage(argc+optind, argv-optind, 1); | 115 | print_usage(argc+optind, argv-optind, 1); |
| 116 | return -1; | 116 | return 1; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | if (argc == 2) { | 119 | if (argc == 2) { |
| @@ -123,7 +123,7 @@ int main(int argc, char **argv) | |||
| 123 | mode = RESET_LOCATION; | 123 | mode = RESET_LOCATION; |
| 124 | } else { | 124 | } else { |
| 125 | print_usage(argc+optind, argv-optind, 1); | 125 | print_usage(argc+optind, argv-optind, 1); |
| 126 | return -1; | 126 | return 1; |
| 127 | } | 127 | } |
| 128 | } | 128 | } |
| 129 | 129 | ||
| @@ -135,19 +135,30 @@ int main(int argc, char **argv) | |||
| 135 | } else { | 135 | } else { |
| 136 | printf("ERROR: No device found!\n"); | 136 | printf("ERROR: No device found!\n"); |
| 137 | } | 137 | } |
| 138 | return -1; | 138 | return 1; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | lockdownd_client_t lockdown; | 141 | lockdownd_client_t lockdown = NULL; |
| 142 | lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME); | 142 | lockdownd_error_t lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME); |
| 143 | if (lerr != LOCKDOWN_E_SUCCESS) { | ||
| 144 | idevice_free(device); | ||
| 145 | printf("ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(lerr), lerr); | ||
| 146 | return 1; | ||
| 147 | } | ||
| 143 | 148 | ||
| 144 | lockdownd_service_descriptor_t svc = NULL; | 149 | lockdownd_service_descriptor_t svc = NULL; |
| 145 | lockdownd_error_t lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc); | 150 | lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc); |
| 146 | if (lerr != LOCKDOWN_E_SUCCESS) { | 151 | if (lerr != LOCKDOWN_E_SUCCESS) { |
| 152 | unsigned int device_version = idevice_get_device_version(device); | ||
| 147 | lockdownd_client_free(lockdown); | 153 | lockdownd_client_free(lockdown); |
| 148 | idevice_free(device); | 154 | idevice_free(device); |
| 149 | printf("ERROR: Could not start the simulatelocation service: %s\nMake sure a developer disk image is mounted!\n", lockdownd_strerror(lerr)); | 155 | printf("ERROR: Could not start the simulatelocation service: %s\n", lockdownd_strerror(lerr)); |
| 150 | return -1; | 156 | if (device_version >= IDEVICE_DEVICE_VERSION(17,0,0)) { |
| 157 | printf("Note: This tool is currently not supported on iOS 17+\n"); | ||
| 158 | } else { | ||
| 159 | printf("Make sure a developer disk image is mounted!\n"); | ||
| 160 | } | ||
| 161 | return 1; | ||
| 151 | } | 162 | } |
| 152 | lockdownd_client_free(lockdown); | 163 | lockdownd_client_free(lockdown); |
| 153 | 164 | ||
| @@ -158,10 +169,9 @@ int main(int argc, char **argv) | |||
| 158 | lockdownd_service_descriptor_free(svc); | 169 | lockdownd_service_descriptor_free(svc); |
| 159 | 170 | ||
| 160 | if (serr != SERVICE_E_SUCCESS) { | 171 | if (serr != SERVICE_E_SUCCESS) { |
| 161 | lockdownd_client_free(lockdown); | ||
| 162 | idevice_free(device); | 172 | idevice_free(device); |
| 163 | printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr); | 173 | printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr); |
| 164 | return -1; | 174 | return 1; |
| 165 | } | 175 | } |
| 166 | 176 | ||
| 167 | uint32_t l; | 177 | uint32_t l; |
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c index a0e641d..88af4c1 100644 --- a/tools/idevicesyslog.c +++ b/tools/idevicesyslog.c | |||
| @@ -33,8 +33,9 @@ | |||
| 33 | #include <stdlib.h> | 33 | #include <stdlib.h> |
| 34 | #include <unistd.h> | 34 | #include <unistd.h> |
| 35 | #include <getopt.h> | 35 | #include <getopt.h> |
| 36 | #include <time.h> | ||
| 36 | 37 | ||
| 37 | #ifdef WIN32 | 38 | #ifdef _WIN32 |
| 38 | #include <windows.h> | 39 | #include <windows.h> |
| 39 | #define sleep(x) Sleep(x*1000) | 40 | #define sleep(x) Sleep(x*1000) |
| 40 | #endif | 41 | #endif |
| @@ -42,10 +43,12 @@ | |||
| 42 | #include <libimobiledevice/libimobiledevice.h> | 43 | #include <libimobiledevice/libimobiledevice.h> |
| 43 | #include <libimobiledevice/syslog_relay.h> | 44 | #include <libimobiledevice/syslog_relay.h> |
| 44 | #include <libimobiledevice-glue/termcolors.h> | 45 | #include <libimobiledevice-glue/termcolors.h> |
| 46 | #include <libimobiledevice/ostrace.h> | ||
| 45 | 47 | ||
| 46 | static int quit_flag = 0; | 48 | static int quit_flag = 0; |
| 47 | static int exit_on_disconnect = 0; | 49 | static int exit_on_disconnect = 0; |
| 48 | static int show_device_name = 0; | 50 | static int show_device_name = 0; |
| 51 | static int force_syslog_relay = 0; | ||
| 49 | 52 | ||
| 50 | static char* udid = NULL; | 53 | static char* udid = NULL; |
| 51 | static char** proc_filters = NULL; | 54 | static char** proc_filters = NULL; |
| @@ -58,6 +61,9 @@ static int num_pid_filters = 0; | |||
| 58 | static char** msg_filters = NULL; | 61 | static char** msg_filters = NULL; |
| 59 | static int num_msg_filters = 0; | 62 | static int num_msg_filters = 0; |
| 60 | 63 | ||
| 64 | static char** msg_reverse_filters = NULL; | ||
| 65 | static int num_msg_reverse_filters = 0; | ||
| 66 | |||
| 61 | static char** trigger_filters = NULL; | 67 | static char** trigger_filters = NULL; |
| 62 | static int num_trigger_filters = 0; | 68 | static int num_trigger_filters = 0; |
| 63 | static char** untrigger_filters = NULL; | 69 | static char** untrigger_filters = NULL; |
| @@ -66,11 +72,16 @@ static int triggered = 0; | |||
| 66 | 72 | ||
| 67 | static idevice_t device = NULL; | 73 | static idevice_t device = NULL; |
| 68 | static syslog_relay_client_t syslog = NULL; | 74 | static syslog_relay_client_t syslog = NULL; |
| 75 | static ostrace_client_t ostrace = NULL; | ||
| 69 | 76 | ||
| 70 | static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd"; | 77 | static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd"; |
| 71 | 78 | ||
| 72 | static int use_network = 0; | 79 | static int use_network = 0; |
| 73 | 80 | ||
| 81 | static long long start_time = -1; | ||
| 82 | static long long size_limit = -1; | ||
| 83 | static long long age_limit = -1; | ||
| 84 | |||
| 74 | static char *line = NULL; | 85 | static char *line = NULL; |
| 75 | static int line_buffer_size = 0; | 86 | static int line_buffer_size = 0; |
| 76 | static int lp = 0; | 87 | static int lp = 0; |
| @@ -129,6 +140,70 @@ static int find_char(char c, char** p, const char* end) | |||
| 129 | 140 | ||
| 130 | static void stop_logging(void); | 141 | static void stop_logging(void); |
| 131 | 142 | ||
| 143 | static int message_filter_matching(const char* message) | ||
| 144 | { | ||
| 145 | if (num_msg_filters > 0) { | ||
| 146 | int found = 0; | ||
| 147 | int i; | ||
| 148 | for (i = 0; i < num_msg_filters; i++) { | ||
| 149 | if (strstr(message, msg_filters[i])) { | ||
| 150 | found = 1; | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | if (!found) { | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | if (num_msg_reverse_filters > 0) { | ||
| 159 | int found = 0; | ||
| 160 | int i; | ||
| 161 | for (i = 0; i < num_msg_reverse_filters; i++) { | ||
| 162 | if (strstr(message, msg_reverse_filters[i])) { | ||
| 163 | found = 1; | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | if (found) { | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | return 1; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int process_filter_matching(int pid, const char* process_name, int process_name_length) | ||
| 175 | { | ||
| 176 | int proc_matched = 0; | ||
| 177 | if (num_pid_filters > 0) { | ||
| 178 | int found = proc_filter_excluding; | ||
| 179 | int i = 0; | ||
| 180 | for (i = 0; i < num_pid_filters; i++) { | ||
| 181 | if (pid == pid_filters[i]) { | ||
| 182 | found = !proc_filter_excluding; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if (found) { | ||
| 187 | proc_matched = 1; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | if (num_proc_filters > 0 && !proc_matched) { | ||
| 191 | int found = proc_filter_excluding; | ||
| 192 | int i = 0; | ||
| 193 | for (i = 0; i < num_proc_filters; i++) { | ||
| 194 | if (!proc_filters[i]) continue; | ||
| 195 | if (strncmp(proc_filters[i], process_name, process_name_length) == 0) { | ||
| 196 | found = !proc_filter_excluding; | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | if (found) { | ||
| 201 | proc_matched = 1; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | return proc_matched; | ||
| 205 | } | ||
| 206 | |||
| 132 | static void syslog_callback(char c, void *user_data) | 207 | static void syslog_callback(char c, void *user_data) |
| 133 | { | 208 | { |
| 134 | if (lp >= line_buffer_size-1) { | 209 | if (lp >= line_buffer_size-1) { |
| @@ -202,20 +277,9 @@ static void syslog_callback(char c, void *user_data) | |||
| 202 | } | 277 | } |
| 203 | 278 | ||
| 204 | /* check message filters */ | 279 | /* check message filters */ |
| 205 | if (num_msg_filters > 0) { | 280 | shall_print = message_filter_matching(device_name_end+1); |
| 206 | int found = 0; | 281 | if (!shall_print) { |
| 207 | int i; | 282 | break; |
| 208 | for (i = 0; i < num_msg_filters; i++) { | ||
| 209 | if (strstr(device_name_end+1, msg_filters[i])) { | ||
| 210 | found = 1; | ||
| 211 | break; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | if (!found) { | ||
| 215 | shall_print = 0; | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | shall_print = 1; | ||
| 219 | } | 283 | } |
| 220 | 284 | ||
| 221 | /* process name */ | 285 | /* process name */ |
| @@ -235,39 +299,10 @@ static void syslog_callback(char c, void *user_data) | |||
| 235 | proc_name_end = p; | 299 | proc_name_end = p; |
| 236 | p++; | 300 | p++; |
| 237 | 301 | ||
| 238 | int proc_matched = 0; | 302 | /* match pid / process name */ |
| 239 | if (num_pid_filters > 0) { | 303 | char* endp = NULL; |
| 240 | char* endp = NULL; | 304 | int pid_value = (int)strtol(pid_start, &endp, 10); |
| 241 | int pid_value = (int)strtol(pid_start, &endp, 10); | 305 | if (process_filter_matching(pid_value, process_name_start, process_name_end-process_name_start)) { |
| 242 | if (endp && (*endp == ']')) { | ||
| 243 | int found = proc_filter_excluding; | ||
| 244 | int i = 0; | ||
| 245 | for (i = 0; i < num_pid_filters; i++) { | ||
| 246 | if (pid_value == pid_filters[i]) { | ||
| 247 | found = !proc_filter_excluding; | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | if (found) { | ||
| 252 | proc_matched = 1; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | if (num_proc_filters > 0 && !proc_matched) { | ||
| 257 | int found = proc_filter_excluding; | ||
| 258 | int i = 0; | ||
| 259 | for (i = 0; i < num_proc_filters; i++) { | ||
| 260 | if (!proc_filters[i]) continue; | ||
| 261 | if (strncmp(proc_filters[i], process_name_start, process_name_end-process_name_start) == 0) { | ||
| 262 | found = !proc_filter_excluding; | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | if (found) { | ||
| 267 | proc_matched = 1; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | if (proc_matched) { | ||
| 271 | shall_print = 1; | 306 | shall_print = 1; |
| 272 | } else { | 307 | } else { |
| 273 | if (num_pid_filters > 0 || num_proc_filters > 0) { | 308 | if (num_pid_filters > 0 || num_proc_filters > 0) { |
| @@ -331,7 +366,7 @@ static void syslog_callback(char c, void *user_data) | |||
| 331 | } | 366 | } |
| 332 | } while (0); | 367 | } while (0); |
| 333 | 368 | ||
| 334 | if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) { | 369 | if ((num_msg_filters == 0 && num_msg_reverse_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) { |
| 335 | fwrite(linep, 1, lp, stdout); | 370 | fwrite(linep, 1, lp, stdout); |
| 336 | cprintf(COLOR_RESET); | 371 | cprintf(COLOR_RESET); |
| 337 | fflush(stdout); | 372 | fflush(stdout); |
| @@ -345,12 +380,231 @@ static void syslog_callback(char c, void *user_data) | |||
| 345 | } | 380 | } |
| 346 | } | 381 | } |
| 347 | 382 | ||
| 348 | static int start_logging(void) | 383 | static void ostrace_syslog_callback(const void* buf, size_t len, void* user_data) |
| 349 | { | 384 | { |
| 350 | idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); | 385 | if (len < 0x81) { |
| 351 | if (ret != IDEVICE_E_SUCCESS) { | 386 | fprintf(stderr, "Error: not enough data in callback function?!\n"); |
| 352 | fprintf(stderr, "Device with udid %s not found!?\n", udid); | 387 | return; |
| 353 | return -1; | 388 | } |
| 389 | |||
| 390 | struct ostrace_packet_header_t *trace_hdr = (struct ostrace_packet_header_t*)buf; | ||
| 391 | |||
| 392 | if (trace_hdr->marker != 2 || (trace_hdr->type != 8 && trace_hdr->type != 2)) { | ||
| 393 | fprintf(stderr, "unexpected packet data %02x %08x\n", trace_hdr->marker, trace_hdr->type); | ||
| 394 | } | ||
| 395 | |||
| 396 | const char* dataptr = (const char*)buf + trace_hdr->header_size; | ||
| 397 | const char* process_name = dataptr; | ||
| 398 | const char* image_name = (trace_hdr->imagepath_len > 0) ? dataptr + trace_hdr->procpath_len : NULL; | ||
| 399 | const char* message = (trace_hdr->message_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len : NULL; | ||
| 400 | //const char* subsystem = (trace_hdr->subsystem_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len : NULL; | ||
| 401 | //const char* category = (trace_hdr->category_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len + trace_hdr->subsystem_len : NULL; | ||
| 402 | |||
| 403 | int shall_print = 1; | ||
| 404 | int trigger_off = 0; | ||
| 405 | const char* process_name_short = (process_name) ? strrchr(process_name, '/') : ""; | ||
| 406 | process_name_short = (process_name_short) ? process_name_short+1 : process_name; | ||
| 407 | const char* image_name_short = (image_name) ? strrchr(image_name, '/') : NULL; | ||
| 408 | image_name_short = (image_name_short) ? image_name_short+1 : process_name; | ||
| 409 | if (image_name_short && !strcmp(image_name_short, process_name_short)) { | ||
| 410 | image_name_short = NULL; | ||
| 411 | } | ||
| 412 | |||
| 413 | do { | ||
| 414 | /* check if we have any triggers/untriggers */ | ||
| 415 | if (num_untrigger_filters > 0 && triggered) { | ||
| 416 | int found = 0; | ||
| 417 | int i; | ||
| 418 | for (i = 0; i < num_untrigger_filters; i++) { | ||
| 419 | if (strstr(message, untrigger_filters[i])) { | ||
| 420 | found = 1; | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | if (!found) { | ||
| 425 | shall_print = 1; | ||
| 426 | } else { | ||
| 427 | shall_print = 1; | ||
| 428 | trigger_off = 1; | ||
| 429 | } | ||
| 430 | } else if (num_trigger_filters > 0 && !triggered) { | ||
| 431 | int found = 0; | ||
| 432 | int i; | ||
| 433 | for (i = 0; i < num_trigger_filters; i++) { | ||
| 434 | if (strstr(message, trigger_filters[i])) { | ||
| 435 | found = 1; | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | if (!found) { | ||
| 440 | shall_print = 0; | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | triggered = 1; | ||
| 444 | shall_print = 1; | ||
| 445 | } else if (num_trigger_filters == 0 && num_untrigger_filters > 0 && !triggered) { | ||
| 446 | shall_print = 0; | ||
| 447 | quit_flag++; | ||
| 448 | break; | ||
| 449 | } | ||
| 450 | |||
| 451 | /* check message filters */ | ||
| 452 | shall_print = message_filter_matching(message); | ||
| 453 | if (!shall_print) { | ||
| 454 | break; | ||
| 455 | } | ||
| 456 | |||
| 457 | /* check process filters */ | ||
| 458 | if (process_filter_matching(trace_hdr->pid, process_name_short, strlen(process_name_short))) { | ||
| 459 | shall_print = 1; | ||
| 460 | } else { | ||
| 461 | if (num_pid_filters > 0 || num_proc_filters > 0) { | ||
| 462 | shall_print = 0; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | if (!shall_print) { | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | } while (0); | ||
| 469 | |||
| 470 | if (!shall_print) { | ||
| 471 | return; | ||
| 472 | } | ||
| 473 | |||
| 474 | const char* level_str = "Unknown"; | ||
| 475 | const char* level_color = FG_YELLOW; | ||
| 476 | switch (trace_hdr->level) { | ||
| 477 | case 0: | ||
| 478 | level_str = "Notice"; | ||
| 479 | level_color = FG_GREEN; | ||
| 480 | break; | ||
| 481 | case 0x01: | ||
| 482 | level_str = "Info"; | ||
| 483 | level_color = FG_WHITE; | ||
| 484 | break; | ||
| 485 | case 0x02: | ||
| 486 | level_str = "Debug"; | ||
| 487 | level_color = FG_MAGENTA; | ||
| 488 | break; | ||
| 489 | case 0x10: | ||
| 490 | level_str = "Error"; | ||
| 491 | level_color = FG_RED; | ||
| 492 | break; | ||
| 493 | case 0x11: | ||
| 494 | level_str = "Fault"; | ||
| 495 | level_color = FG_RED; | ||
| 496 | default: | ||
| 497 | break; | ||
| 498 | } | ||
| 499 | |||
| 500 | char datebuf[24]; | ||
| 501 | struct tm *tp; | ||
| 502 | time_t time_sec = (time_t)trace_hdr->time_sec; | ||
| 503 | #ifdef HAVE_LOCALTIME_R | ||
| 504 | struct tm tp_ = {0, }; | ||
| 505 | tp = localtime_r(&time_sec, &tp_); | ||
| 506 | #else | ||
| 507 | tp = localtime(&time_sec); | ||
| 508 | #endif | ||
| 509 | #ifdef _WIN32 | ||
| 510 | strftime(datebuf, 16, "%b %#d %H:%M:%S", tp); | ||
| 511 | #else | ||
| 512 | strftime(datebuf, 16, "%b %e %H:%M:%S", tp); | ||
| 513 | #endif | ||
| 514 | snprintf(datebuf+15, 9, ".%06u", trace_hdr->time_usec); | ||
| 515 | |||
| 516 | /* write date and time */ | ||
| 517 | cprintf(FG_LIGHT_GRAY "%s ", datebuf); | ||
| 518 | |||
| 519 | if (show_device_name) { | ||
| 520 | /* write device name TODO do we need this? */ | ||
| 521 | //cprintf(FG_DARK_YELLOW "%s ", device_name); | ||
| 522 | } | ||
| 523 | |||
| 524 | /* write process name */ | ||
| 525 | cprintf(FG_BRIGHT_CYAN "%s" FG_CYAN, process_name_short); | ||
| 526 | if (image_name_short) { | ||
| 527 | cprintf("(%s)", image_name_short); | ||
| 528 | } | ||
| 529 | cprintf("[%d]" COLOR_RESET " ", trace_hdr->pid); | ||
| 530 | |||
| 531 | /* write log level */ | ||
| 532 | cprintf(level_color); | ||
| 533 | cprintf("<%s>:" COLOR_RESET " ", level_str); | ||
| 534 | |||
| 535 | /* write message */ | ||
| 536 | cprintf(FG_WHITE); | ||
| 537 | cprintf("%s" COLOR_RESET "\n", message); | ||
| 538 | fflush(stdout); | ||
| 539 | |||
| 540 | if (trigger_off) { | ||
| 541 | triggered = 0; | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | static plist_t get_pid_list() | ||
| 546 | { | ||
| 547 | plist_t list = NULL; | ||
| 548 | ostrace_client_t ostrace_tmp = NULL; | ||
| 549 | ostrace_client_start_service(device, &ostrace_tmp, TOOL_NAME); | ||
| 550 | if (ostrace_tmp) { | ||
| 551 | ostrace_get_pid_list(ostrace_tmp, &list); | ||
| 552 | ostrace_client_free(ostrace_tmp); | ||
| 553 | } | ||
| 554 | return list; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int pid_valid(int pid) | ||
| 558 | { | ||
| 559 | plist_t list = get_pid_list(); | ||
| 560 | if (!list) return 0; | ||
| 561 | char valbuf[16]; | ||
| 562 | snprintf(valbuf, 16, "%d", pid); | ||
| 563 | return (plist_dict_get_item(list, valbuf)) ? 1 : 0; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int pid_for_proc(const char* procname) | ||
| 567 | { | ||
| 568 | int result = -1; | ||
| 569 | plist_t list = get_pid_list(); | ||
| 570 | if (!list) { | ||
| 571 | return result; | ||
| 572 | } | ||
| 573 | plist_dict_iter iter = NULL; | ||
| 574 | plist_dict_new_iter(list, &iter); | ||
| 575 | if (iter) { | ||
| 576 | plist_t node = NULL; | ||
| 577 | do { | ||
| 578 | char* key = NULL; | ||
| 579 | node = NULL; | ||
| 580 | plist_dict_next_item(list, iter, &key, &node); | ||
| 581 | if (!key) { | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | if (PLIST_IS_DICT(node)) { | ||
| 585 | plist_t pname = plist_dict_get_item(node, "ProcessName"); | ||
| 586 | if (PLIST_IS_STRING(pname)) { | ||
| 587 | if (!strcmp(plist_get_string_ptr(pname, NULL), procname)) { | ||
| 588 | result = (int)strtol(key, NULL, 10); | ||
| 589 | } | ||
| 590 | } | ||
| 591 | } | ||
| 592 | free(key); | ||
| 593 | } while (node); | ||
| 594 | plist_mem_free(iter); | ||
| 595 | } | ||
| 596 | plist_free(list); | ||
| 597 | return result; | ||
| 598 | } | ||
| 599 | |||
| 600 | static int connect_service(int ostrace_required) | ||
| 601 | { | ||
| 602 | if (!device) { | ||
| 603 | idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); | ||
| 604 | if (ret != IDEVICE_E_SUCCESS) { | ||
| 605 | fprintf(stderr, "Device with udid %s not found!?\n", udid); | ||
| 606 | return -1; | ||
| 607 | } | ||
| 354 | } | 608 | } |
| 355 | 609 | ||
| 356 | lockdownd_client_t lockdown = NULL; | 610 | lockdownd_client_t lockdown = NULL; |
| @@ -361,14 +615,28 @@ static int start_logging(void) | |||
| 361 | device = NULL; | 615 | device = NULL; |
| 362 | return -1; | 616 | return -1; |
| 363 | } | 617 | } |
| 364 | |||
| 365 | /* start syslog_relay service */ | ||
| 366 | lockdownd_service_descriptor_t svc = NULL; | 618 | lockdownd_service_descriptor_t svc = NULL; |
| 367 | lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); | 619 | |
| 620 | const char* service_name = OSTRACE_SERVICE_NAME; | ||
| 621 | int use_ostrace = 1; | ||
| 622 | if (idevice_get_device_version(device) < IDEVICE_DEVICE_VERSION(9,0,0) || force_syslog_relay) { | ||
| 623 | service_name = SYSLOG_RELAY_SERVICE_NAME; | ||
| 624 | use_ostrace = 0; | ||
| 625 | } | ||
| 626 | if (ostrace_required && !use_ostrace) { | ||
| 627 | fprintf(stderr, "ERROR: This operation requires iOS 9 or later.\n"); | ||
| 628 | lockdownd_client_free(lockdown); | ||
| 629 | idevice_free(device); | ||
| 630 | device = NULL; | ||
| 631 | return -1; | ||
| 632 | } | ||
| 633 | |||
| 634 | /* start syslog_relay/os_trace_relay service */ | ||
| 635 | lerr = lockdownd_start_service(lockdown, service_name, &svc); | ||
| 368 | if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { | 636 | if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { |
| 369 | fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n"); | 637 | fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n"); |
| 370 | while (!quit_flag) { | 638 | while (!quit_flag) { |
| 371 | lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); | 639 | lerr = lockdownd_start_service(lockdown, service_name, &svc); |
| 372 | if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) { | 640 | if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) { |
| 373 | break; | 641 | break; |
| 374 | } | 642 | } |
| @@ -376,32 +644,84 @@ static int start_logging(void) | |||
| 376 | } | 644 | } |
| 377 | } | 645 | } |
| 378 | if (lerr != LOCKDOWN_E_SUCCESS) { | 646 | if (lerr != LOCKDOWN_E_SUCCESS) { |
| 379 | fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr); | 647 | fprintf(stderr, "ERROR: Could not start %s service: %s (%d)\n", service_name, lockdownd_strerror(lerr), lerr); |
| 380 | idevice_free(device); | 648 | idevice_free(device); |
| 381 | device = NULL; | 649 | device = NULL; |
| 382 | return -1; | 650 | return -1; |
| 383 | } | 651 | } |
| 384 | lockdownd_client_free(lockdown); | 652 | lockdownd_client_free(lockdown); |
| 385 | 653 | ||
| 386 | /* connect to syslog_relay service */ | 654 | if (use_ostrace) { |
| 387 | syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; | 655 | /* connect to os_trace_relay service */ |
| 388 | serr = syslog_relay_client_new(device, svc, &syslog); | 656 | ostrace_error_t serr = OSTRACE_E_UNKNOWN_ERROR; |
| 389 | lockdownd_service_descriptor_free(svc); | 657 | serr = ostrace_client_new(device, svc, &ostrace); |
| 390 | if (serr != SYSLOG_RELAY_E_SUCCESS) { | 658 | lockdownd_service_descriptor_free(svc); |
| 391 | fprintf(stderr, "ERROR: Could not start service com.apple.syslog_relay.\n"); | 659 | if (serr != OSTRACE_E_SUCCESS) { |
| 392 | idevice_free(device); | 660 | fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr); |
| 393 | device = NULL; | 661 | idevice_free(device); |
| 662 | device = NULL; | ||
| 663 | return -1; | ||
| 664 | } | ||
| 665 | } else { | ||
| 666 | /* connect to syslog_relay service */ | ||
| 667 | syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; | ||
| 668 | serr = syslog_relay_client_new(device, svc, &syslog); | ||
| 669 | lockdownd_service_descriptor_free(svc); | ||
| 670 | if (serr != SYSLOG_RELAY_E_SUCCESS) { | ||
| 671 | fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr); | ||
| 672 | idevice_free(device); | ||
| 673 | device = NULL; | ||
| 674 | return -1; | ||
| 675 | } | ||
| 676 | } | ||
| 677 | return 0; | ||
| 678 | } | ||
| 679 | |||
| 680 | static int start_logging(void) | ||
| 681 | { | ||
| 682 | if (connect_service(0) < 0) { | ||
| 394 | return -1; | 683 | return -1; |
| 395 | } | 684 | } |
| 396 | 685 | ||
| 397 | /* start capturing syslog */ | 686 | /* start capturing syslog */ |
| 398 | serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); | 687 | if (ostrace) { |
| 399 | if (serr != SYSLOG_RELAY_E_SUCCESS) { | 688 | plist_t options = plist_new_dict(); |
| 400 | fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n"); | 689 | if (num_proc_filters == 0 && num_pid_filters == 1 && !proc_filter_excluding) { |
| 401 | syslog_relay_client_free(syslog); | 690 | if (pid_filters[0] > 0) { |
| 402 | syslog = NULL; | 691 | if (!pid_valid(pid_filters[0])) { |
| 403 | idevice_free(device); | 692 | fprintf(stderr, "NOTE: A process with pid doesn't exists!\n"); |
| 404 | device = NULL; | 693 | } |
| 694 | } | ||
| 695 | plist_dict_set_item(options, "Pid", plist_new_int(pid_filters[0])); | ||
| 696 | } else if (num_proc_filters == 1 && num_pid_filters == 0 && !proc_filter_excluding) { | ||
| 697 | int pid = pid_for_proc(proc_filters[0]); | ||
| 698 | if (!strcmp(proc_filters[0], "kernel")) { | ||
| 699 | pid = 0; | ||
| 700 | } | ||
| 701 | if (pid >= 0) { | ||
| 702 | plist_dict_set_item(options, "Pid", plist_new_int(pid)); | ||
| 703 | } | ||
| 704 | } | ||
| 705 | ostrace_error_t serr = ostrace_start_activity(ostrace, options, ostrace_syslog_callback, NULL); | ||
| 706 | if (serr != OSTRACE_E_SUCCESS) { | ||
| 707 | fprintf(stderr, "ERROR: Unable to start capturing syslog.\n"); | ||
| 708 | ostrace_client_free(ostrace); | ||
| 709 | ostrace = NULL; | ||
| 710 | idevice_free(device); | ||
| 711 | device = NULL; | ||
| 712 | return -1; | ||
| 713 | } | ||
| 714 | } else if (syslog) { | ||
| 715 | syslog_relay_error_t serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); | ||
| 716 | if (serr != SYSLOG_RELAY_E_SUCCESS) { | ||
| 717 | fprintf(stderr, "ERROR: Unable to start capturing syslog.\n"); | ||
| 718 | syslog_relay_client_free(syslog); | ||
| 719 | syslog = NULL; | ||
| 720 | idevice_free(device); | ||
| 721 | device = NULL; | ||
| 722 | return -1; | ||
| 723 | } | ||
| 724 | } else { | ||
| 405 | return -1; | 725 | return -1; |
| 406 | } | 726 | } |
| 407 | 727 | ||
| @@ -419,6 +739,11 @@ static void stop_logging(void) | |||
| 419 | syslog_relay_client_free(syslog); | 739 | syslog_relay_client_free(syslog); |
| 420 | syslog = NULL; | 740 | syslog = NULL; |
| 421 | } | 741 | } |
| 742 | if (ostrace) { | ||
| 743 | ostrace_stop_activity(ostrace); | ||
| 744 | ostrace_client_free(ostrace); | ||
| 745 | ostrace = NULL; | ||
| 746 | } | ||
| 422 | 747 | ||
| 423 | if (device) { | 748 | if (device) { |
| 424 | idevice_free(device); | 749 | idevice_free(device); |
| @@ -426,6 +751,77 @@ static void stop_logging(void) | |||
| 426 | } | 751 | } |
| 427 | } | 752 | } |
| 428 | 753 | ||
| 754 | static int write_callback(const void* buf, size_t len, void *user_data) | ||
| 755 | { | ||
| 756 | FILE* f = (FILE*)user_data; | ||
| 757 | ssize_t res = fwrite(buf, 1, len, f); | ||
| 758 | if (res < 0) { | ||
| 759 | return -1; | ||
| 760 | } | ||
| 761 | if (quit_flag > 0) { | ||
| 762 | return -1; | ||
| 763 | } | ||
| 764 | return 0; | ||
| 765 | } | ||
| 766 | |||
| 767 | static void print_sorted_pidlist(plist_t list) | ||
| 768 | { | ||
| 769 | struct listelem; | ||
| 770 | struct listelem { | ||
| 771 | int val; | ||
| 772 | struct listelem *next; | ||
| 773 | }; | ||
| 774 | struct listelem* sortedlist = NULL; | ||
| 775 | |||
| 776 | plist_dict_iter iter = NULL; | ||
| 777 | plist_dict_new_iter(list, &iter); | ||
| 778 | if (iter) { | ||
| 779 | plist_t node = NULL; | ||
| 780 | do { | ||
| 781 | char* key = NULL; | ||
| 782 | node = NULL; | ||
| 783 | plist_dict_next_item(list, iter, &key, &node); | ||
| 784 | if (key) { | ||
| 785 | int pidval = (int)strtol(key, NULL, 10); | ||
| 786 | struct listelem* elem = (struct listelem*)malloc(sizeof(struct listelem)); | ||
| 787 | elem->val = pidval; | ||
| 788 | elem->next = NULL; | ||
| 789 | struct listelem* prev = NULL; | ||
| 790 | struct listelem* curr = sortedlist; | ||
| 791 | |||
| 792 | while (curr && pidval > curr->val) { | ||
| 793 | prev = curr; | ||
| 794 | curr = curr->next; | ||
| 795 | } | ||
| 796 | |||
| 797 | elem->next = curr; | ||
| 798 | if (prev == NULL) { | ||
| 799 | sortedlist = elem; | ||
| 800 | } else { | ||
| 801 | prev->next = elem; | ||
| 802 | } | ||
| 803 | free(key); | ||
| 804 | } | ||
| 805 | } while (node); | ||
| 806 | plist_mem_free(iter); | ||
| 807 | } | ||
| 808 | struct listelem *listp = sortedlist; | ||
| 809 | char pidstr[16]; | ||
| 810 | while (listp) { | ||
| 811 | snprintf(pidstr, 16, "%d", listp->val); | ||
| 812 | plist_t node = plist_dict_get_item(list, pidstr); | ||
| 813 | if (PLIST_IS_DICT(node)) { | ||
| 814 | plist_t pname = plist_dict_get_item(node, "ProcessName"); | ||
| 815 | if (PLIST_IS_STRING(pname)) { | ||
| 816 | printf("%d %s\n", listp->val, plist_get_string_ptr(pname, NULL)); | ||
| 817 | } | ||
| 818 | } | ||
| 819 | struct listelem *curr = listp; | ||
| 820 | listp = listp->next; | ||
| 821 | free(curr); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 429 | static void device_event_cb(const idevice_event_t* event, void* userdata) | 825 | static void device_event_cb(const idevice_event_t* event, void* userdata) |
| 430 | { | 826 | { |
| 431 | if (use_network && event->conn_type != CONNECTION_NETWORK) { | 827 | if (use_network && event->conn_type != CONNECTION_NETWORK) { |
| @@ -435,7 +831,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata) | |||
| 435 | return; | 831 | return; |
| 436 | } | 832 | } |
| 437 | if (event->event == IDEVICE_DEVICE_ADD) { | 833 | if (event->event == IDEVICE_DEVICE_ADD) { |
| 438 | if (!syslog) { | 834 | if (!syslog && !ostrace) { |
| 439 | if (!udid) { | 835 | if (!udid) { |
| 440 | udid = strdup(event->udid); | 836 | udid = strdup(event->udid); |
| 441 | } | 837 | } |
| @@ -446,7 +842,7 @@ static void device_event_cb(const idevice_event_t* event, void* userdata) | |||
| 446 | } | 842 | } |
| 447 | } | 843 | } |
| 448 | } else if (event->event == IDEVICE_DEVICE_REMOVE) { | 844 | } else if (event->event == IDEVICE_DEVICE_REMOVE) { |
| 449 | if (syslog && (strcmp(udid, event->udid) == 0)) { | 845 | if ((syslog || ostrace) && (strcmp(udid, event->udid) == 0)) { |
| 450 | stop_logging(); | 846 | stop_logging(); |
| 451 | fprintf(stdout, "[disconnected:%s]\n", udid); | 847 | fprintf(stdout, "[disconnected:%s]\n", udid); |
| 452 | if (exit_on_disconnect) { | 848 | if (exit_on_disconnect) { |
| @@ -484,9 +880,20 @@ static void print_usage(int argc, char **argv, int is_error) | |||
| 484 | " -o, --output FILE write to FILE instead of stdout\n" | 880 | " -o, --output FILE write to FILE instead of stdout\n" |
| 485 | " (existing FILE will be overwritten)\n" | 881 | " (existing FILE will be overwritten)\n" |
| 486 | " --colors force writing colored output, e.g. for --output\n" | 882 | " --colors force writing colored output, e.g. for --output\n" |
| 883 | " --syslog-relay force use of syslog_relay service\n" | ||
| 884 | "\n" | ||
| 885 | "COMMANDS:\n" | ||
| 886 | " pidlist Print pid and name of all running processes.\n" | ||
| 887 | " archive PATH Request a logarchive and write it to PATH.\n" | ||
| 888 | " Output can be piped to another process using - as PATH.\n" | ||
| 889 | " The file data will be in .tar format.\n" | ||
| 890 | " --start-time VALUE start time of the log data as UNIX timestamp\n" | ||
| 891 | " --age-limit VALUE maximum age of the log data\n" | ||
| 892 | " --size-limit VALUE limit the size of the archive\n" | ||
| 487 | "\n" | 893 | "\n" |
| 488 | "FILTER OPTIONS:\n" | 894 | "FILTER OPTIONS:\n" |
| 489 | " -m, --match STRING only print messages that contain STRING\n" | 895 | " -m, --match STRING only print messages that contain STRING\n" |
| 896 | " -M, --unmatch STRING print messages that not contain STRING\n" | ||
| 490 | " -t, --trigger STRING start logging when matching STRING\n" | 897 | " -t, --trigger STRING start logging when matching STRING\n" |
| 491 | " -T, --untrigger STRING stop logging when matching STRING\n" | 898 | " -T, --untrigger STRING stop logging when matching STRING\n" |
| 492 | " -p, --process PROCESS only print messages from matching process(es)\n" | 899 | " -p, --process PROCESS only print messages from matching process(es)\n" |
| @@ -530,6 +937,12 @@ int main(int argc, char *argv[]) | |||
| 530 | { "quiet-list", no_argument, NULL, 1 }, | 937 | { "quiet-list", no_argument, NULL, 1 }, |
| 531 | { "no-colors", no_argument, NULL, 2 }, | 938 | { "no-colors", no_argument, NULL, 2 }, |
| 532 | { "colors", no_argument, NULL, 3 }, | 939 | { "colors", no_argument, NULL, 3 }, |
| 940 | { "syslog_relay", no_argument, NULL, 4 }, | ||
| 941 | { "syslog-relay", no_argument, NULL, 4 }, | ||
| 942 | { "legacy", no_argument, NULL, 4 }, | ||
| 943 | { "start-time", required_argument, NULL, 5 }, | ||
| 944 | { "size-limit", required_argument, NULL, 6 }, | ||
| 945 | { "age-limit", required_argument, NULL, 7 }, | ||
| 533 | { "output", required_argument, NULL, 'o' }, | 946 | { "output", required_argument, NULL, 'o' }, |
| 534 | { "version", no_argument, NULL, 'v' }, | 947 | { "version", no_argument, NULL, 'v' }, |
| 535 | { NULL, 0, NULL, 0} | 948 | { NULL, 0, NULL, 0} |
| @@ -537,12 +950,12 @@ int main(int argc, char *argv[]) | |||
| 537 | 950 | ||
| 538 | signal(SIGINT, clean_exit); | 951 | signal(SIGINT, clean_exit); |
| 539 | signal(SIGTERM, clean_exit); | 952 | signal(SIGTERM, clean_exit); |
| 540 | #ifndef WIN32 | 953 | #ifndef _WIN32 |
| 541 | signal(SIGQUIT, clean_exit); | 954 | signal(SIGQUIT, clean_exit); |
| 542 | signal(SIGPIPE, SIG_IGN); | 955 | signal(SIGPIPE, SIG_IGN); |
| 543 | #endif | 956 | #endif |
| 544 | 957 | ||
| 545 | while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:e:p:qkKo:v", longopts, NULL)) != -1) { | 958 | while ((c = getopt_long(argc, argv, "dhu:nxt:T:m:M:e:p:qkKo:v", longopts, NULL)) != -1) { |
| 546 | switch (c) { | 959 | switch (c) { |
| 547 | case 'd': | 960 | case 'd': |
| 548 | idevice_set_debug_level(1); | 961 | idevice_set_debug_level(1); |
| @@ -593,6 +1006,22 @@ int main(int argc, char *argv[]) | |||
| 593 | num_msg_filters++; | 1006 | num_msg_filters++; |
| 594 | } | 1007 | } |
| 595 | break; | 1008 | break; |
| 1009 | case 'M': | ||
| 1010 | if (!*optarg) { | ||
| 1011 | fprintf(stderr, "ERROR: reverse message filter string must not be empty!\n"); | ||
| 1012 | print_usage(argc, argv, 1); | ||
| 1013 | return 2; | ||
| 1014 | } else { | ||
| 1015 | char **new_msg_filters = realloc(msg_reverse_filters, sizeof(char*) * (num_msg_reverse_filters+1)); | ||
| 1016 | if (!new_msg_filters) { | ||
| 1017 | fprintf(stderr, "ERROR: realloc() failed\n"); | ||
| 1018 | exit(EXIT_FAILURE); | ||
| 1019 | } | ||
| 1020 | msg_reverse_filters = new_msg_filters; | ||
| 1021 | msg_reverse_filters[num_msg_reverse_filters] = strdup(optarg); | ||
| 1022 | num_msg_reverse_filters++; | ||
| 1023 | } | ||
| 1024 | break; | ||
| 596 | case 't': | 1025 | case 't': |
| 597 | if (!*optarg) { | 1026 | if (!*optarg) { |
| 598 | fprintf(stderr, "ERROR: trigger filter string must not be empty!\n"); | 1027 | fprintf(stderr, "ERROR: trigger filter string must not be empty!\n"); |
| @@ -647,6 +1076,18 @@ int main(int argc, char *argv[]) | |||
| 647 | case 3: | 1076 | case 3: |
| 648 | force_colors = 1; | 1077 | force_colors = 1; |
| 649 | break; | 1078 | break; |
| 1079 | case 4: | ||
| 1080 | force_syslog_relay = 1; | ||
| 1081 | break; | ||
| 1082 | case 5: | ||
| 1083 | start_time = strtoll(optarg, NULL, 10); | ||
| 1084 | break; | ||
| 1085 | case 6: | ||
| 1086 | size_limit = strtoll(optarg, NULL, 10); | ||
| 1087 | break; | ||
| 1088 | case 7: | ||
| 1089 | age_limit = strtoll(optarg, NULL, 10); | ||
| 1090 | break; | ||
| 650 | case 'o': | 1091 | case 'o': |
| 651 | if (!*optarg) { | 1092 | if (!*optarg) { |
| 652 | fprintf(stderr, "ERROR: --output option requires an argument!\n"); | 1093 | fprintf(stderr, "ERROR: --output option requires an argument!\n"); |
| @@ -719,14 +1160,92 @@ int main(int argc, char *argv[]) | |||
| 719 | argc -= optind; | 1160 | argc -= optind; |
| 720 | argv += optind; | 1161 | argv += optind; |
| 721 | 1162 | ||
| 1163 | if (argc > 0) { | ||
| 1164 | if (!strcmp(argv[0], "pidlist")) { | ||
| 1165 | if (connect_service(1) < 0) { | ||
| 1166 | return 1; | ||
| 1167 | } | ||
| 1168 | plist_t list = NULL; | ||
| 1169 | ostrace_get_pid_list(ostrace, &list); | ||
| 1170 | ostrace_client_free(ostrace); | ||
| 1171 | ostrace = NULL; | ||
| 1172 | idevice_free(device); | ||
| 1173 | device = NULL; | ||
| 1174 | if (!list) { | ||
| 1175 | return 1; | ||
| 1176 | } | ||
| 1177 | print_sorted_pidlist(list); | ||
| 1178 | plist_free(list); | ||
| 1179 | return 0; | ||
| 1180 | } else if (!strcmp(argv[0], "archive")) { | ||
| 1181 | if (force_syslog_relay) { | ||
| 1182 | force_syslog_relay = 0; | ||
| 1183 | } | ||
| 1184 | if (argc < 2) { | ||
| 1185 | fprintf(stderr, "Please specify an output filename.\n"); | ||
| 1186 | return 1; | ||
| 1187 | } | ||
| 1188 | FILE* outf = NULL; | ||
| 1189 | if (!strcmp(argv[1], "-")) { | ||
| 1190 | if (isatty(1)) { | ||
| 1191 | fprintf(stderr, "Refusing to directly write to stdout. Pipe the output to another process.\n"); | ||
| 1192 | return 1; | ||
| 1193 | } | ||
| 1194 | outf = stdout; | ||
| 1195 | } else { | ||
| 1196 | outf = fopen(argv[1], "w"); | ||
| 1197 | } | ||
| 1198 | if (!outf) { | ||
| 1199 | fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); | ||
| 1200 | return 1; | ||
| 1201 | } | ||
| 1202 | if (connect_service(1) < 0) { | ||
| 1203 | if (outf != stdout) { | ||
| 1204 | fclose(outf); | ||
| 1205 | } | ||
| 1206 | return 1; | ||
| 1207 | } | ||
| 1208 | plist_t options = plist_new_dict(); | ||
| 1209 | if (start_time > 0) { | ||
| 1210 | plist_dict_set_item(options, "StartTime", plist_new_int(start_time)); | ||
| 1211 | } | ||
| 1212 | if (size_limit > 0) { | ||
| 1213 | plist_dict_set_item(options, "SizeLimit", plist_new_int(size_limit)); | ||
| 1214 | } | ||
| 1215 | if (age_limit > 0) { | ||
| 1216 | plist_dict_set_item(options, "AgeLimit", plist_new_int(age_limit)); | ||
| 1217 | } | ||
| 1218 | ostrace_create_archive(ostrace, options, write_callback, outf); | ||
| 1219 | ostrace_client_free(ostrace); | ||
| 1220 | ostrace = NULL; | ||
| 1221 | idevice_free(device); | ||
| 1222 | device = NULL; | ||
| 1223 | if (outf != stdout) { | ||
| 1224 | fclose(outf); | ||
| 1225 | } | ||
| 1226 | return 0; | ||
| 1227 | } else { | ||
| 1228 | fprintf(stderr, "Unknown command '%s'. See --help for valid commands.\n", argv[0]); | ||
| 1229 | return 1; | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | |||
| 722 | int num = 0; | 1233 | int num = 0; |
| 723 | idevice_info_t *devices = NULL; | 1234 | idevice_info_t *devices = NULL; |
| 724 | idevice_get_device_list_extended(&devices, &num); | 1235 | idevice_get_device_list_extended(&devices, &num); |
| 1236 | int count = 0; | ||
| 1237 | for (int i = 0; i < num; i++) { | ||
| 1238 | if (devices[i]->conn_type == CONNECTION_NETWORK && use_network) { | ||
| 1239 | count++; | ||
| 1240 | } else if (devices[i]->conn_type == CONNECTION_USBMUXD) { | ||
| 1241 | count++; | ||
| 1242 | } | ||
| 1243 | } | ||
| 725 | idevice_device_list_extended_free(devices); | 1244 | idevice_device_list_extended_free(devices); |
| 726 | if (num == 0) { | 1245 | if (count == 0) { |
| 727 | if (!udid) { | 1246 | if (!udid) { |
| 728 | fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); | 1247 | fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to become available.\n"); |
| 729 | return -1; | 1248 | return 1; |
| 730 | } | 1249 | } |
| 731 | 1250 | ||
| 732 | fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid); | 1251 | fprintf(stderr, "Waiting for device with UDID %s to become available...\n", udid); |
| @@ -761,6 +1280,13 @@ int main(int argc, char *argv[]) | |||
| 761 | } | 1280 | } |
| 762 | free(msg_filters); | 1281 | free(msg_filters); |
| 763 | } | 1282 | } |
| 1283 | if (num_msg_reverse_filters > 0) { | ||
| 1284 | int i; | ||
| 1285 | for (i = 0; i < num_msg_reverse_filters; i++) { | ||
| 1286 | free(msg_reverse_filters[i]); | ||
| 1287 | } | ||
| 1288 | free(msg_reverse_filters); | ||
| 1289 | } | ||
| 764 | if (num_trigger_filters > 0) { | 1290 | if (num_trigger_filters > 0) { |
| 765 | int i; | 1291 | int i; |
| 766 | for (i = 0; i < num_trigger_filters; i++) { | 1292 | for (i = 0; i < num_trigger_filters; i++) { |
