diff options
Diffstat (limited to 'cython/afc.pxi')
-rw-r--r-- | cython/afc.pxi | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/cython/afc.pxi b/cython/afc.pxi new file mode 100644 index 0000000..6bd8182 --- /dev/null +++ b/cython/afc.pxi | |||
@@ -0,0 +1,337 @@ | |||
1 | cdef extern from "libimobiledevice/afc.h": | ||
2 | cdef struct afc_client_private: | ||
3 | pass | ||
4 | ctypedef afc_client_private *afc_client_t | ||
5 | ctypedef enum afc_error_t: | ||
6 | AFC_E_SUCCESS = 0 | ||
7 | AFC_E_UNKNOWN_ERROR = 1 | ||
8 | AFC_E_OP_HEADER_INVALID = 2 | ||
9 | AFC_E_NO_RESOURCES = 3 | ||
10 | AFC_E_READ_ERROR = 4 | ||
11 | AFC_E_WRITE_ERROR = 5 | ||
12 | AFC_E_UNKNOWN_PACKET_TYPE = 6 | ||
13 | AFC_E_INVALID_ARG = 7 | ||
14 | AFC_E_OBJECT_NOT_FOUND = 8 | ||
15 | AFC_E_OBJECT_IS_DIR = 9 | ||
16 | AFC_E_PERM_DENIED = 10 | ||
17 | AFC_E_SERVICE_NOT_CONNECTED = 11 | ||
18 | AFC_E_OP_TIMEOUT = 12 | ||
19 | AFC_E_TOO_MUCH_DATA = 13 | ||
20 | AFC_E_END_OF_DATA = 14 | ||
21 | AFC_E_OP_NOT_SUPPORTED = 15 | ||
22 | AFC_E_OBJECT_EXISTS = 16 | ||
23 | AFC_E_OBJECT_BUSY = 17 | ||
24 | AFC_E_NO_SPACE_LEFT = 18 | ||
25 | AFC_E_OP_WOULD_BLOCK = 19 | ||
26 | AFC_E_IO_ERROR = 20 | ||
27 | AFC_E_OP_INTERRUPTED = 21 | ||
28 | AFC_E_OP_IN_PROGRESS = 22 | ||
29 | AFC_E_INTERNAL_ERROR = 23 | ||
30 | AFC_E_MUX_ERROR = 30 | ||
31 | AFC_E_NO_MEM = 31 | ||
32 | AFC_E_NOT_ENOUGH_DATA = 32 | ||
33 | AFC_E_DIR_NOT_EMPTY = 33 | ||
34 | ctypedef enum afc_file_mode_t: | ||
35 | AFC_FOPEN_RDONLY = 0x00000001 | ||
36 | AFC_FOPEN_RW = 0x00000002 | ||
37 | AFC_FOPEN_WRONLY = 0x00000003 | ||
38 | AFC_FOPEN_WR = 0x00000004 | ||
39 | AFC_FOPEN_APPEND = 0x00000005 | ||
40 | AFC_FOPEN_RDAPPEND = 0x00000006 | ||
41 | ctypedef enum afc_link_type_t: | ||
42 | AFC_HARDLINK = 1 | ||
43 | AFC_SYMLINK = 2 | ||
44 | ctypedef enum afc_lock_op_t: | ||
45 | AFC_LOCK_SH = 1 | 4 | ||
46 | AFC_LOCK_EX = 2 | 4 | ||
47 | AFC_LOCK_UN = 8 | 4 | ||
48 | |||
49 | afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, afc_client_t *client) | ||
50 | afc_error_t afc_client_free(afc_client_t client) | ||
51 | afc_error_t afc_get_device_info(afc_client_t client, char ***infos) | ||
52 | afc_error_t afc_read_directory(afc_client_t client, char *dir, char ***list) | ||
53 | afc_error_t afc_get_file_info(afc_client_t client, char *filename, char ***infolist) | ||
54 | afc_error_t afc_remove_path(afc_client_t client, char *path) | ||
55 | afc_error_t afc_remove_path_and_contents(afc_client_t client, char *path) | ||
56 | afc_error_t afc_rename_path(afc_client_t client, char *f, char *to) | ||
57 | afc_error_t afc_make_directory(afc_client_t client, char *dir) | ||
58 | afc_error_t afc_truncate(afc_client_t client, char *path, uint64_t newsize) | ||
59 | afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, char *target, char *linkname) | ||
60 | afc_error_t afc_set_file_time(afc_client_t client, char *path, uint64_t mtime) | ||
61 | |||
62 | afc_error_t afc_file_open(afc_client_t client, char *filename, afc_file_mode_t file_mode, uint64_t *handle) | ||
63 | afc_error_t afc_file_close(afc_client_t client, uint64_t handle) | ||
64 | afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t operation) | ||
65 | afc_error_t afc_file_read(afc_client_t client, uint64_t handle, char *data, uint32_t length, uint32_t *bytes_read) | ||
66 | afc_error_t afc_file_write(afc_client_t client, uint64_t handle, char *data, uint32_t length, uint32_t *bytes_written) | ||
67 | afc_error_t afc_file_seek(afc_client_t client, uint64_t handle, int64_t offset, int whence) | ||
68 | afc_error_t afc_file_tell(afc_client_t client, uint64_t handle, uint64_t *position) | ||
69 | afc_error_t afc_file_truncate(afc_client_t client, uint64_t handle, uint64_t newsize) | ||
70 | |||
71 | LOCK_SH = AFC_LOCK_SH | ||
72 | LOCK_EX = AFC_LOCK_EX | ||
73 | LOCK_UN = AFC_LOCK_UN | ||
74 | |||
75 | cdef class AfcError(BaseError): | ||
76 | def __init__(self, *args, **kwargs): | ||
77 | self._lookup_table = { | ||
78 | AFC_E_SUCCESS: "Success", | ||
79 | AFC_E_UNKNOWN_ERROR: "Unknown error", | ||
80 | AFC_E_OP_HEADER_INVALID: "OP header invalid", | ||
81 | AFC_E_NO_RESOURCES: "No resources", | ||
82 | AFC_E_READ_ERROR: "Read error", | ||
83 | AFC_E_WRITE_ERROR: "Write error", | ||
84 | AFC_E_UNKNOWN_PACKET_TYPE: "Unknown packet type", | ||
85 | AFC_E_INVALID_ARG: "Invalid argument", | ||
86 | AFC_E_OBJECT_NOT_FOUND: "Object not found", | ||
87 | AFC_E_OBJECT_IS_DIR: "Object is directory", | ||
88 | AFC_E_PERM_DENIED: "Permission denied", | ||
89 | AFC_E_SERVICE_NOT_CONNECTED: "Service not connected", | ||
90 | AFC_E_OP_TIMEOUT: "OP timeout", | ||
91 | AFC_E_TOO_MUCH_DATA: "Too much data", | ||
92 | AFC_E_END_OF_DATA: "End of data", | ||
93 | AFC_E_OP_NOT_SUPPORTED: "OP not supported", | ||
94 | AFC_E_OBJECT_EXISTS: "Object exists", | ||
95 | AFC_E_OBJECT_BUSY: "Object busy", | ||
96 | AFC_E_NO_SPACE_LEFT: "No space left", | ||
97 | AFC_E_OP_WOULD_BLOCK: "OP would block", | ||
98 | AFC_E_IO_ERROR: "IO error", | ||
99 | AFC_E_OP_INTERRUPTED: "OP interrupted", | ||
100 | AFC_E_OP_IN_PROGRESS: "OP in progress", | ||
101 | AFC_E_INTERNAL_ERROR: "Internal error", | ||
102 | AFC_E_MUX_ERROR: "MUX error", | ||
103 | AFC_E_NO_MEM: "No memory", | ||
104 | AFC_E_NOT_ENOUGH_DATA: "Not enough data", | ||
105 | AFC_E_DIR_NOT_EMPTY: "Directory not empty" | ||
106 | } | ||
107 | BaseError.__init__(self, *args, **kwargs) | ||
108 | |||
109 | # forward declaration of AfcClient | ||
110 | cdef class AfcClient(BaseService) | ||
111 | |||
112 | cdef class AfcFile(Base): | ||
113 | cdef uint64_t _c_handle | ||
114 | cdef AfcClient _client | ||
115 | cdef bytes _filename | ||
116 | |||
117 | def __init__(self, *args, **kwargs): | ||
118 | raise TypeError("AfcFile cannot be instantiated") | ||
119 | |||
120 | def __enter__(self): | ||
121 | return self | ||
122 | |||
123 | def __exit__(self, type, value, traceback): | ||
124 | self.close() | ||
125 | |||
126 | cpdef close(self): | ||
127 | self.handle_error(afc_file_close(self._client._c_client, self._c_handle)) | ||
128 | |||
129 | cpdef lock(self, int operation): | ||
130 | self.handle_error(afc_file_lock(self._client._c_client, self._c_handle, <afc_lock_op_t>operation)) | ||
131 | |||
132 | cpdef seek(self, int64_t offset, int whence): | ||
133 | self.handle_error(afc_file_seek(self._client._c_client, self._c_handle, offset, whence)) | ||
134 | |||
135 | cpdef uint64_t tell(self): | ||
136 | cdef uint64_t position | ||
137 | self.handle_error(afc_file_tell(self._client._c_client, self._c_handle, &position)) | ||
138 | return position | ||
139 | |||
140 | cpdef truncate(self, uint64_t newsize): | ||
141 | self.handle_error(afc_file_truncate(self._client._c_client, self._c_handle, newsize)) | ||
142 | |||
143 | cpdef bytes read(self, uint32_t size): | ||
144 | cdef: | ||
145 | uint32_t bytes_read | ||
146 | char* c_data = <char *>malloc(size) | ||
147 | bytes result | ||
148 | try: | ||
149 | self.handle_error(afc_file_read(self._client._c_client, self._c_handle, c_data, size, &bytes_read)) | ||
150 | result = c_data[:bytes_read] | ||
151 | return result | ||
152 | except BaseError, e: | ||
153 | raise | ||
154 | finally: | ||
155 | free(c_data) | ||
156 | |||
157 | cpdef uint32_t write(self, bytes data): | ||
158 | cdef: | ||
159 | uint32_t bytes_written | ||
160 | char* c_data = data | ||
161 | try: | ||
162 | self.handle_error(afc_file_write(self._client._c_client, self._c_handle, c_data, len(data), &bytes_written)) | ||
163 | except BaseError, e: | ||
164 | raise | ||
165 | |||
166 | return bytes_written | ||
167 | |||
168 | cdef inline BaseError _error(self, int16_t ret): | ||
169 | return AfcError(ret) | ||
170 | |||
171 | cdef class AfcClient(BaseService): | ||
172 | __service_name__ = "com.apple.afc" | ||
173 | cdef afc_client_t _c_client | ||
174 | |||
175 | def __cinit__(self, iDevice device = None, LockdownServiceDescriptor descriptor = None, *args, **kwargs): | ||
176 | if (device is not None and descriptor is not None): | ||
177 | self.handle_error(afc_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) | ||
178 | |||
179 | def __dealloc__(self): | ||
180 | cdef afc_error_t err | ||
181 | if self._c_client is not NULL: | ||
182 | err = afc_client_free(self._c_client) | ||
183 | self.handle_error(err) | ||
184 | |||
185 | cdef BaseError _error(self, int16_t ret): | ||
186 | return AfcError(ret) | ||
187 | |||
188 | cpdef list get_device_info(self): | ||
189 | cdef: | ||
190 | afc_error_t err | ||
191 | char** infos = NULL | ||
192 | bytes info | ||
193 | int i = 0 | ||
194 | list result = [] | ||
195 | err = afc_get_device_info(self._c_client, &infos) | ||
196 | try: | ||
197 | self.handle_error(err) | ||
198 | except BaseError, e: | ||
199 | raise | ||
200 | finally: | ||
201 | if infos != NULL: | ||
202 | while infos[i]: | ||
203 | info = infos[i] | ||
204 | result.append(info) | ||
205 | free(infos[i]) | ||
206 | i = i + 1 | ||
207 | free(infos) | ||
208 | |||
209 | return result | ||
210 | |||
211 | cpdef list read_directory(self, bytes directory): | ||
212 | cdef: | ||
213 | afc_error_t err | ||
214 | char** dir_list = NULL | ||
215 | bytes f | ||
216 | int i = 0 | ||
217 | list result = [] | ||
218 | err = afc_read_directory(self._c_client, directory, &dir_list) | ||
219 | try: | ||
220 | self.handle_error(err) | ||
221 | except BaseError, e: | ||
222 | raise | ||
223 | finally: | ||
224 | if dir_list != NULL: | ||
225 | while dir_list[i]: | ||
226 | f = dir_list[i] | ||
227 | result.append(f) | ||
228 | free(dir_list[i]) | ||
229 | i = i + 1 | ||
230 | free(dir_list) | ||
231 | |||
232 | return result | ||
233 | |||
234 | cpdef AfcFile open(self, bytes filename, bytes mode=b'r'): | ||
235 | cdef: | ||
236 | afc_file_mode_t c_mode | ||
237 | uint64_t handle | ||
238 | AfcFile f | ||
239 | if mode == b'r': | ||
240 | c_mode = AFC_FOPEN_RDONLY | ||
241 | elif mode == b'r+': | ||
242 | c_mode = AFC_FOPEN_RW | ||
243 | elif mode == b'w': | ||
244 | c_mode = AFC_FOPEN_WRONLY | ||
245 | elif mode == b'w+': | ||
246 | c_mode = AFC_FOPEN_WR | ||
247 | elif mode == b'a': | ||
248 | c_mode = AFC_FOPEN_APPEND | ||
249 | elif mode == b'a+': | ||
250 | c_mode = AFC_FOPEN_RDAPPEND | ||
251 | else: | ||
252 | raise ValueError("mode string must be 'r', 'r+', 'w', 'w+', 'a', or 'a+'") | ||
253 | |||
254 | self.handle_error(afc_file_open(self._c_client, filename, c_mode, &handle)) | ||
255 | f = AfcFile.__new__(AfcFile) | ||
256 | f._c_handle = handle | ||
257 | f._client = self | ||
258 | f._filename = filename | ||
259 | |||
260 | return f | ||
261 | |||
262 | cpdef list get_file_info(self, bytes path): | ||
263 | cdef: | ||
264 | list result = [] | ||
265 | char** c_result = NULL | ||
266 | int i = 0 | ||
267 | bytes info | ||
268 | try: | ||
269 | self.handle_error(afc_get_file_info(self._c_client, path, &c_result)) | ||
270 | except BaseError, e: | ||
271 | raise | ||
272 | finally: | ||
273 | if c_result != NULL: | ||
274 | while c_result[i]: | ||
275 | info = c_result[i] | ||
276 | result.append(info) | ||
277 | free(c_result[i]) | ||
278 | i = i + 1 | ||
279 | free(c_result) | ||
280 | |||
281 | return result | ||
282 | |||
283 | cpdef remove_path(self, bytes path): | ||
284 | self.handle_error(afc_remove_path(self._c_client, path)) | ||
285 | |||
286 | cpdef remove_path_and_contents(self, bytes path): | ||
287 | self.handle_error(afc_remove_path_and_contents(self._c_client, path)) | ||
288 | |||
289 | cpdef rename_path(self, bytes f, bytes t): | ||
290 | self.handle_error(afc_rename_path(self._c_client, f, t)) | ||
291 | |||
292 | cpdef make_directory(self, bytes d): | ||
293 | self.handle_error(afc_make_directory(self._c_client, d)) | ||
294 | |||
295 | cpdef truncate(self, bytes path, uint64_t newsize): | ||
296 | self.handle_error(afc_truncate(self._c_client, path, newsize)) | ||
297 | |||
298 | cpdef link(self, bytes source, bytes link_name): | ||
299 | self.handle_error(afc_make_link(self._c_client, AFC_HARDLINK, source, link_name)) | ||
300 | |||
301 | cpdef symlink(self, bytes source, bytes link_name): | ||
302 | self.handle_error(afc_make_link(self._c_client, AFC_SYMLINK, source, link_name)) | ||
303 | |||
304 | cpdef set_file_time(self, bytes path, uint64_t mtime): | ||
305 | self.handle_error(afc_set_file_time(self._c_client, path, mtime)) | ||
306 | |||
307 | cdef class Afc2Client(AfcClient): | ||
308 | __service_name__ = "com.apple.afc2" | ||
309 | |||
310 | cpdef AfcFile open(self, bytes filename, bytes mode=b'r'): | ||
311 | cdef: | ||
312 | afc_file_mode_t c_mode | ||
313 | uint64_t handle | ||
314 | AfcFile f | ||
315 | if mode == b'r': | ||
316 | c_mode = AFC_FOPEN_RDONLY | ||
317 | elif mode == b'r+': | ||
318 | c_mode = AFC_FOPEN_RW | ||
319 | elif mode == b'w': | ||
320 | c_mode = AFC_FOPEN_WRONLY | ||
321 | elif mode == b'w+': | ||
322 | c_mode = AFC_FOPEN_WR | ||
323 | elif mode == b'a': | ||
324 | c_mode = AFC_FOPEN_APPEND | ||
325 | elif mode == b'a+': | ||
326 | c_mode = AFC_FOPEN_RDAPPEND | ||
327 | else: | ||
328 | raise ValueError("mode string must be 'r', 'r+', 'w', 'w+', 'a', or 'a+'") | ||
329 | |||
330 | self.handle_error(afc_file_open(self._c_client, filename, c_mode, &handle)) | ||
331 | f = AfcFile.__new__(AfcFile) | ||
332 | f._c_handle = handle | ||
333 | f._client = <AfcClient>self | ||
334 | f._filename = filename | ||
335 | |||
336 | return f | ||
337 | |||