/** Retrieves the file size of a file on an iPhone. * @param iphone The iPhone on which to locate the file. * @param path The UNIX style path to the file on the iPhone. * @return The size of the file. */ long iPhone_GetFileSize(iPhone *iphone, char *path) { if(iphone->connected) { void *data = NULL; int ret = AFCFileInfoOpen(iphone->hAFC, path, &data); if(ret == 0 && data != NULL) { void *name, *val; while(AFCKeyValueRead(data, &name, &val) == 0 && name != NULL && val != NULL) { if(strcmp(name, "st_size") == 0) { return atol(val); } } AFCKeyValueClose(data); } } return 0; }
/** Retrieves the type of the file. * @param iphone The iPhone on which to locate the file. * @param path The UNIX style path to the file on the iPhone. * @return AMD_FILE for regular file, AMD_DIR for directory, and AMD_LINK for hard or symbolic links. */ int iPhone_GetFileType(iPhone *iphone, char *path) { if(iphone->connected) { void *data = NULL; int ret = AFCFileInfoOpen(iphone->hAFC, path, &data); if(ret == 0 && data != NULL) { void *name, *val; while(AFCKeyValueRead(data, &name, &val) == 0 && name != NULL && val != NULL) { if(strcmp(name, "st_ifmt") == 0) { if(strcmp(val, "S_IFREG") == 0) return AMD_FILE; else if(strcmp(val, "S_IFDIR") == 0) return AMD_DIR; else if(strcmp(val, "S_IFLNK") == 0) return AMD_LINK; else return AMD_UNKNOWN; } } AFCKeyValueClose(data); } } return AMD_UNKNOWN; }
// Puts the information on a particular file in the pInfo structure. // // Returns: // MDERR_OK when successful // MDERR_AFC_NOT_FOUND if the file couldn't be found (or is a broken link) // t_MachError CiPoTApi::GetFileInfo(char *remotePath, t_iPodFileInfo *pInfo, t_iPodExtraInfo *pExtra) { t_MachError ret; struct afc_dictionary *pDict; char *pKey, *pVal; CString filename; CMacPath MacPath; if (!remotePath) { // If remotePath is not specified, then create it filename.SetString(pInfo->remotePath); if (filename.Right(1).Compare("\\")) //[0] == '\\' filename += "\\"; filename += pInfo->findData.cFileName; remotePath = filename.GetBuffer(); } MacPath.SetWindowsPath(remotePath); memset(pInfo, 0, sizeof(FILETIME)*3 + sizeof(DWORD)*3); if (pExtra) memset(pExtra, 0, sizeof(t_iPodExtraInfo)); // if (pInfo->findData.cFileName[0] == '.') // pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN; if ((ret = AFCFileInfoOpen(m_iPodConnection, MacPath.GetBuffer(), &pDict)) != MDERR_OK) return ret; AFCKeyValueRead(pDict, &pKey, &pVal); while(pKey || pVal) { if (!strcmp(pKey, "st_ifmt")) { if (!strcmp(pVal, "S_IFIFO")) { // pipe pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (pExtra) pExtra->iType = IPOD_IFIFO; } else if (!strcmp(pVal, "S_IFCHR")) { // character special pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (pExtra) pExtra->iType = IPOD_IFCHR; } else if (!strcmp(pVal, "S_IFBLK")) { // block special pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (pExtra) pExtra->iType = IPOD_IFBLK; } else if (!strcmp(pVal, "S_IFSOCK")) { // socket pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (pExtra) pExtra->iType = IPOD_IFSOCK; } else if (!strcmp(pVal, "S_IFLNK")) { // symbolic link pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (pExtra) pExtra->iType = IPOD_IFLNK; } else if (!strcmp(pVal, "S_IFDIR")) { // directory pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; if (pExtra) pExtra->iType = IPOD_IFDIR; } else if (!strcmp(pVal, "S_IFREG")) { // regular pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL; if (pExtra) pExtra->iType = IPOD_IFREG; } } else if (!strcmp(pKey, "st_size")) { pInfo->findData.nFileSizeLow = strtol(pVal, NULL, 10); if (pExtra) pExtra->iSize = pInfo->findData.nFileSizeLow; } else if (!strcmp(pKey, "st_blocks")) { if (pExtra) pExtra->iBlocks = atoi(pVal); } else if (!strcmp(pKey, "st_nlink")) { if (pExtra) pExtra->iLinks = atoi(pVal); } else if (!strcmp(pKey, "LinkTarget")) { if (pExtra) strcpy(pExtra->LinkTarget, pVal); // Acquire info about the link target. pExtra will contain link info, so leave it alone char cFullPath[MAX_PATH]; GetLinkTargetPath(remotePath, pVal, cFullPath); int iRet = GetFileInfo(cFullPath, pInfo, 0); pInfo->findData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM; if (iRet == MDERR_OK) break; else if (pExtra) pExtra->iType = IPOD_IFBLNK; } AFCKeyValueRead(pDict, &pKey, &pVal); } if (pInfo->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) pInfo->findData.nFileSizeLow = 0; AFCKeyValueClose(pDict); return MDERR_OK; }
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()); }