Skip to content

Commit 66edd7d

Browse files
committed
feat: add afc.WalkDirectory
1 parent a825f89 commit 66edd7d

File tree

7 files changed

+220
-25
lines changed

7 files changed

+220
-25
lines changed

afc/afc.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package afc
2+
3+
// #cgo pkg-config: libimobiledevice-1.0
4+
// #include <stdlib.h>
5+
// #include <libimobiledevice/afc.h>
6+
// int afc_length(char **arr)
7+
// {
8+
// int length = 0;
9+
// int k = 0;
10+
// for (k = 0; arr[k] != NULL; k++) {
11+
// length = length + 1;
12+
// }
13+
// return length;
14+
// }
15+
import "C"
16+
import (
17+
"unsafe"
18+
19+
"github.com/nowsecure/goidevice/idevice"
20+
"github.com/nowsecure/goidevice/lockdown"
21+
)
22+
23+
type AFC struct {
24+
a C.afc_client_t
25+
}
26+
27+
func NewClient(device idevice.Device, svc *lockdown.Service) (*AFC, error) {
28+
var a C.afc_client_t
29+
err := resultToError(
30+
C.afc_client_new(
31+
(C.idevice_t)(idevice.GetPointer(device)),
32+
(C.lockdownd_service_descriptor_t)(svc.GetDescriptor()),
33+
&a,
34+
),
35+
)
36+
return &AFC{a}, err
37+
}
38+
39+
func (a *AFC) WalkDirectory(path string) ([]SourceFile, error) {
40+
dir, err := a.ReadDirectory(path)
41+
if err != nil {
42+
return []SourceFile{}, err
43+
}
44+
45+
files := []SourceFile{}
46+
for _, f := range dir {
47+
if f.format == "S_IFDIR" {
48+
childDir, err := a.WalkDirectory(f.Name)
49+
if err != nil {
50+
return []SourceFile{}, err
51+
}
52+
files = append(files, childDir...)
53+
continue
54+
}
55+
files = append(files, f)
56+
}
57+
return files, nil
58+
}
59+
60+
type SourceFile struct {
61+
Name string
62+
63+
format string
64+
}
65+
66+
func (a *AFC) ReadDirectory(path string) ([]SourceFile, error) {
67+
var directoryC **C.char
68+
defer C.afc_dictionary_free(directoryC)
69+
70+
sourceFiles := []SourceFile{}
71+
pathC := C.CString(path)
72+
defer C.free(unsafe.Pointer(pathC))
73+
74+
err := resultToError(C.afc_read_directory(a.a, pathC, &directoryC))
75+
if err != nil {
76+
return []SourceFile{}, err
77+
}
78+
79+
directory := unsafe.Slice(directoryC, C.afc_length(directoryC))
80+
for i := range directory {
81+
file := SourceFile{
82+
Name: C.GoString(directory[i]),
83+
}
84+
if file.Name == ".." || file.Name == "." {
85+
continue
86+
}
87+
88+
var fileInfoC **C.char
89+
C.afc_get_file_info(a.a, directory[i], &fileInfoC)
90+
if fileInfoC != nil {
91+
fileInfo := unsafe.Slice(fileInfoC, C.afc_length(fileInfoC))
92+
93+
for j := 0; j < len(fileInfo); j += 2 {
94+
if C.GoString(fileInfo[j]) == "st_ifmt" {
95+
file.format = C.GoString(fileInfo[j+1])
96+
}
97+
}
98+
}
99+
C.afc_dictionary_free(fileInfoC)
100+
sourceFiles = append(sourceFiles, file)
101+
}
102+
return sourceFiles, nil
103+
}

afc/errors.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package afc
2+
3+
// #cgo pkg-config: libimobiledevice-1.0
4+
// #include <stdlib.h>
5+
// #include <libimobiledevice/afc.h>
6+
import "C"
7+
import (
8+
"errors"
9+
"fmt"
10+
)
11+
12+
func resultToError(result C.afc_error_t) error {
13+
switch result {
14+
case 0:
15+
return nil
16+
default:
17+
fmt.Println(result)
18+
return errors.New("unknown")
19+
}
20+
}

installation/installation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package installation
77
//
88
// void instproxy_client_options_add_pair(plist_t client_opts, char * key, char * value)
99
// {
10-
// instproxy_client_options_add(client_opts, key, value, NULL);
10+
// instproxy_client_options_add(client_opts, key, value, NULL);
1111
// }
1212
import "C"
1313
import (

lockdown/errors.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package lockdown
22

33
// #cgo pkg-config: libimobiledevice-1.0
44
// #include <libimobiledevice/lockdown.h>
5+
// #include <libimobiledevice/service.h>
56
import "C"
67
import (
78
"errors"
@@ -174,3 +175,24 @@ func resultToError(result C.lockdownd_error_t) error {
174175
return ErrUnknown
175176
}
176177
}
178+
179+
func serviceResultToError(result C.service_error_t) error {
180+
switch result {
181+
case 0:
182+
return nil
183+
case -1:
184+
return errors.New("invalid args")
185+
case -3:
186+
return errors.New("mux error")
187+
case -4:
188+
return errors.New("ssl error")
189+
case -5:
190+
return errors.New("start service error")
191+
case -6:
192+
return errors.New("not enough data error")
193+
case -7:
194+
return errors.New("timeout")
195+
default:
196+
return errors.New("unknown")
197+
}
198+
}

lockdown/lockdown.go

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ type Client interface {
2121
ValidatePair() error
2222
DeviceName() (string, error)
2323
PList(domain string) (*plist.PList, error)
24-
Close() error
24+
Free() error
25+
GetClient() unsafe.Pointer
2526
StartService(d idevice.Device, serviceName string) (*Service, error)
27+
StartServiceClient(d idevice.Device, serviceName string) (*Service, error)
2628
}
2729

2830
type client struct {
@@ -99,39 +101,63 @@ func (s *client) PList(domain string) (*plist.PList, error) {
99101
return list, nil
100102
}
101103

102-
func (s *client) Close() error {
103-
err := resultToError(C.lockdownd_client_free(s.p))
104-
if err == nil {
105-
s.p = nil
106-
}
107-
return err
104+
func (s *client) Free() error {
105+
return resultToError(C.lockdownd_client_free(s.p))
108106
}
109107

110-
type Service struct {
111-
s C.service_client_t
108+
func (s *client) GetClient() unsafe.Pointer {
109+
return unsafe.Pointer(s.p)
112110
}
113111

114-
const (
115-
CRASH_REPORT_MOVER_SERVICE = "com.apple.crashreportmover"
116-
)
112+
// GetDescriptor gets the lockdown descriptor for the service
113+
func (s *Service) GetDescriptor() unsafe.Pointer {
114+
return unsafe.Pointer(s.descriptor)
115+
}
116+
117+
func (s *Service) FreeDescriptor() {
118+
C.lockdownd_service_descriptor_free(s.descriptor)
119+
}
120+
121+
func (s *Service) Free() {
122+
C.lockdownd_service_descriptor_free(s.descriptor)
123+
C.service_client_free(s.s)
124+
}
117125

118126
func (s *client) StartService(d idevice.Device, serviceName string) (*Service, error) {
119127
var p C.lockdownd_service_descriptor_t
120-
121128
svc := C.CString(serviceName)
122129
defer C.free(unsafe.Pointer(svc))
123130
err := resultToError(C.lockdownd_start_service(s.p, svc, &p))
124131
if err != nil {
125132
return nil, err
126133
}
127134

128-
var c C.service_client_t
129-
res := C.service_client_new((C.idevice_t)(idevice.GetPointer(d)), p, &c)
130-
C.lockdownd_service_descriptor_free(p)
131-
if res != 0 {
132-
return nil, errors.New(":(")
135+
return &Service{descriptor: p}, nil
136+
}
137+
138+
type Service struct {
139+
s C.service_client_t
140+
descriptor C.lockdownd_service_descriptor_t
141+
}
142+
143+
const (
144+
CRASH_REPORT_MOVER_SERVICE = "com.apple.crashreportmover"
145+
CRASH_REPORT_COPY_MOBILE_SERVICE = "com.apple.crashreportcopymobile"
146+
)
147+
148+
func (s *client) StartServiceClient(d idevice.Device, serviceName string) (*Service, error) {
149+
svc, err := s.StartService(d, serviceName)
150+
if err != nil {
151+
return nil, err
133152
}
134-
return &Service{c}, nil
153+
154+
err = serviceResultToError(
155+
C.service_client_new((C.idevice_t)(idevice.GetPointer(d)),
156+
svc.descriptor,
157+
&svc.s,
158+
),
159+
)
160+
return svc, err
135161
}
136162

137163
func (s *Service) ReadPing() error {

thing/main.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,47 @@
11
package main
22

33
import (
4+
"fmt"
45
"log"
5-
"os"
66

7+
"github.com/nowsecure/goidevice/afc"
78
"github.com/nowsecure/goidevice/idevice"
89
"github.com/nowsecure/goidevice/lockdown"
910
)
1011

1112
func main() {
12-
device, err := idevice.New(os.Args[1])
13+
device, err := idevice.New("bd133240a37062e545bbbbf664f0011c9f45895d")
1314
if err != nil {
1415
log.Fatal(err)
1516
}
1617
lock, err := lockdown.NewClientWithHandshake(device, "thingy")
1718
if err != nil {
1819
log.Fatal(err)
1920
}
20-
client, err := lock.StartService(device, lockdown.CRASH_REPORT_MOVER_SERVICE)
21+
client, err := lock.StartServiceClient(device, lockdown.CRASH_REPORT_MOVER_SERVICE)
2122
if err != nil {
2223
log.Fatal(err)
2324
}
25+
defer client.Free()
2426
err = client.ReadPing()
2527
if err != nil {
2628
log.Fatal(err)
27-
} else {
28-
log.Println("yay we did it")
2929
}
30+
31+
service, err := lock.StartService(device, lockdown.CRASH_REPORT_COPY_MOBILE_SERVICE)
32+
if err != nil {
33+
log.Fatal(err)
34+
}
35+
defer service.Free()
36+
37+
afc, err := afc.NewClient(device, service)
38+
if err != nil {
39+
log.Fatal(err)
40+
}
41+
k, _ := afc.WalkDirectory(".")
42+
for _, v := range k {
43+
fmt.Println(v)
44+
}
45+
46+
log.Println("yay we did it")
3047
}

thing/main_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "testing"
4+
5+
func Test_ke(t *testing.T) {
6+
main()
7+
}

0 commit comments

Comments
 (0)