// Reads a file from the iPod and stores it on the PC filesystem. // // Returns: // MDERR_OK when successful // MDERR_AFC_NOT_FOUND if the file couldn't be found (or is a broken link) // MDERR_AFC_ACCESS_DENIED if access denied (e.g. directory, dir. link) // -1 if the file could not be entirely read // // TODO: cleaner return error codes // int CiPoTApi::FileRead(char *remotePath, char *localPath) { t_iPodFileInfo info; t_iPodExtraInfo extra; t_MachError ret; unsigned char *buffer; FILE *fLocal; unsigned long total = 0; unsigned int len; afc_file_ref handle; CMacPath MacPath; char linkPath[MAX_PATH]; MacPath.SetWindowsPath(remotePath); ret = GetFileInfo(remotePath, &info, &extra); if (ret != MDERR_OK) return ret; // Resolve symlinks if (extra.iType == IPOD_IFLNK) { GetLinkTargetPath(MacPath.GetBuffer(), extra.LinkTarget, linkPath); MacPath.SetWindowsPath(linkPath); } ret = AFCFileRefOpen(m_iPodConnection, MacPath.GetBuffer(), AFC_FILEMODE_READ, 0, &handle); if (ret != MDERR_OK) return ret; buffer = new unsigned char[FILEREAD_BUFFER_SIZE]; if (buffer) { fLocal = fopen(localPath, "wb"); if (fLocal) { while (total < info.findData.nFileSizeLow) { len = (unsigned int)min(info.findData.nFileSizeLow - total, (unsigned long)FILEREAD_BUFFER_SIZE); ret = AFCFileRefRead(m_iPodConnection, handle, buffer, &len); if (ret != MDERR_OK || !len) break; if (fwrite(buffer, 1, len, fLocal) != len) break; total += len; if (m_ProgressCallBack(remotePath, localPath, (int)(100.0*total/info.findData.nFileSizeLow))) break; } fclose(fLocal); } delete[] buffer; } AFCFileRefClose(m_iPodConnection, handle); return (total == info.findData.nFileSizeLow) ? MDERR_OK : -1; }
void qwrite(afc_connection * afc, const char *from, const char *to) { printf("Sending %s -> %s... ", from, to); afc_file_ref ref; int fd = open(from, O_RDONLY); assert(fd != -1); size_t size = (size_t) lseek(fd, 0, SEEK_END); void *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); assert(buf != MAP_FAILED); AFCFileRefOpen(afc, to, 3, &ref); AFCFileRefWrite(afc, ref, buf, size); AFCFileRefClose(afc, ref); printf("done.\n"); close(fd); }
// Writes a file from the PC filesystem and stores it on the iPod. // // Returns: // MDERR_OK when successful // MDERR_AFC_NOT_FOUND if the file couldn't be found (or is a broken link) // MDERR_AFC_ACCESS_DENIED if access denied (e.g. directory, dir. link) // -1 if the file could not be entirely written // // TODO: cleaner return error codes // int CiPoTApi::FileWrite(char *remotePath, char *localPath) { struct _stat info; t_MachError ret; unsigned char *buffer; FILE *fLocal; unsigned long len, total = 0; afc_file_ref handle; CMacPath MacPath; MacPath.SetWindowsPath(remotePath); if (_stat(localPath, &info)) return MDERR_AFC_NOT_FOUND; ret = AFCFileRefOpen(m_iPodConnection, MacPath.GetBuffer(), AFC_FILEMODE_WRITE, 0, &handle); if (ret != MDERR_OK) return ret; buffer = new unsigned char[FILEREAD_BUFFER_SIZE]; if (buffer) { fLocal = fopen(localPath, "rb"); if (fLocal) { while (total < (unsigned long)info.st_size) { len = min(info.st_size - total, FILEREAD_BUFFER_SIZE); len = fread(buffer, 1, len, fLocal); if (!len) break; ret = AFCFileRefWrite(m_iPodConnection, handle, buffer, len); if (ret != MDERR_OK) break; total += len; if (m_ProgressCallBack(remotePath, localPath, (int)(100.0*total/info.st_size))) break; } fclose(fLocal); } delete[] buffer; } AFCFileRefClose(m_iPodConnection, handle); return (total == info.st_size) ? MDERR_OK : -1; }
void upload_file(AMDeviceRef device) { service_conn_t houseFd = start_house_arrest_service(device); afc_file_ref file_ref; afc_connection afc_conn; afc_connection* afc_conn_p = &afc_conn; AFCConnectionOpen(houseFd, 0, &afc_conn_p); // read_dir(houseFd, NULL, "/"); if (!target_filename) { target_filename = get_filename_from_path(doc_file_path); } char *target_path = malloc(sizeof("/Documents/") + strlen(target_filename) + 1); strcat(target_path, "/Documents/"); strcat(target_path, target_filename); size_t file_size; void* file_content = read_file_to_memory(doc_file_path, &file_size); if (!file_content) { PRINT("Could not open file: %s\n", doc_file_path); exit(-1); } assert(AFCFileRefOpen(afc_conn_p, target_path, 3, &file_ref) == 0); assert(AFCFileRefWrite(afc_conn_p, file_ref, file_content, file_size) == 0); assert(AFCFileRefClose(afc_conn_p, file_ref) == 0); assert(AFCConnectionClose(afc_conn_p) == 0); free(target_path); free(file_content); }
static void device_notification_callback(am_device_notification_callback_info *info, void *thing) { if (info->msg != ADNCI_MSG_CONNECTED) return; puts("Opened device connection."); am_device *dev = info->dev; AMDeviceConnect(dev); assert(AMDeviceIsPaired(dev)); assert(AMDeviceValidatePairing(dev) == 0); assert(AMDeviceStartSession(dev) == 0); struct afc_connection *afc; service_conn_t afc_conn; assert(AMDeviceStartService(dev, CFSTR("com.apple.afc2"), &afc_conn, NULL) == 0); assert(AFCConnectionOpen(afc_conn, 0, &afc) == 0); char cachepath[63]; const char *caches[3] = {"dyld_shared_cache_armv7s", "dyld_shared_cache_armv7", "dyld_shared_cache_armv6"}; struct afc_dictionary *dict; unsigned int cache_index; char *fullpath; size_t cachesize; for (cache_index=0; cache_index<3; cache_index++) { strcpy(cachepath, "/System/Library/Caches/com.apple.dyld/"); fullpath = strcat(cachepath, caches[cache_index]); if (AFCFileInfoOpen(afc, fullpath, &dict) == 0) { char *key, *value; while (1) { assert(AFCKeyValueRead(dict, &key, &value) == 0); if (key == NULL) break; if (strcmp(key, "st_size") == 0) { cachesize = strtol(value, NULL, 0); break; } } printf("Found cache %s with size %lu\n", fullpath, cachesize); assert(AFCKeyValueClose(dict) == 0); goto _label_hasfile; } } fprintf(stderr, "Could not find cache file.\n"); exit(2); _label_hasfile:; afc_file_ref cache; assert(AFCFileRefOpen(afc, fullpath, 1, &cache) == 0); if (is_cwd) { strcat(outputfile, "/"); strcat(outputfile, caches[cache_index]); gen_path = 1; } puts(outputfile); FILE *output = fopen(outputfile, "w"); assert(output != NULL); printf("Writing cache to %s\n", outputfile); size_t total_bytes = 0; char buffer[65536]; while (1) { unsigned int length = 65536; assert(AFCFileRefRead(afc, cache, buffer, &length) == 0); fwrite(buffer, sizeof(char), length, output); total_bytes += length; float progress = (float)total_bytes/cachesize*100; printf("Progress: %f%%\n\033[F\033[J", progress); if (length < sizeof(buffer)) break; } printf("Successfully wrote cache to %s\n", outputfile); assert(AFCFileRefClose(afc, cache) == 0); CFRunLoopStop(CFRunLoopGetCurrent()); }
static uint32 FileRefClose(AFCCommConnection* Connection, uint64 Handle) { return AFCFileRefClose(Connection, Handle); }