From ec660fff3781444d4deb3a66340dd11d5f3b5a07 Mon Sep 17 00:00:00 2001 From: meancoot Date: Sun, 9 Jun 2013 20:13:05 -0400 Subject: [PATCH] (iOS) Simplify some of the file browser code; add sanity checks for system directories --- ios/RetroArch/RAModuleInfo.m | 2 +- ios/RetroArch/browser/browser.h | 8 +-- ios/RetroArch/browser/browser.m | 119 ++++++++++---------------------- ios/RetroArch/main.m | 14 +++- 4 files changed, 51 insertions(+), 92 deletions(-) diff --git a/ios/RetroArch/RAModuleInfo.m b/ios/RetroArch/RAModuleInfo.m index 56d0ed2a85..0a7834c74e 100644 --- a/ios/RetroArch/RAModuleInfo.m +++ b/ios/RetroArch/RAModuleInfo.m @@ -186,7 +186,7 @@ static NSString* get_data_string(config_file_t* config, const char* name, NSStri cell.detailTextLabel.text = _sections[indexPath.section][indexPath.row * 2 + 2]; if (indexPath.section == _firmwareSectionIndex) - cell.backgroundColor = ra_ios_is_file(_sections[indexPath.section][indexPath.row * 2 + 2]) ? [UIColor blueColor] : [UIColor redColor]; + cell.backgroundColor = path_file_exists(((NSString*)_sections[indexPath.section][indexPath.row * 2 + 2]).UTF8String) ? [UIColor blueColor] : [UIColor redColor]; else cell.backgroundColor = [UIColor whiteColor]; diff --git a/ios/RetroArch/browser/browser.h b/ios/RetroArch/browser/browser.h index ec82cc4bc0..2275554e81 100644 --- a/ios/RetroArch/browser/browser.h +++ b/ios/RetroArch/browser/browser.h @@ -13,13 +13,7 @@ * If not, see . */ -extern BOOL ra_ios_is_directory(NSString* path); -extern BOOL ra_ios_is_file(NSString* path); - -@interface RADirectoryItem : NSObject -@property (strong) NSString* path; -@property bool isDirectory; -@end +#include "file.h" @interface RADirectoryList : UITableViewController + (id)directoryListAtBrowseRoot; diff --git a/ios/RetroArch/browser/browser.m b/ios/RetroArch/browser/browser.m index 46d1daeb9a..0697d28f54 100644 --- a/ios/RetroArch/browser/browser.m +++ b/ios/RetroArch/browser/browser.m @@ -16,85 +16,19 @@ #include #include #import "browser.h" -#import "conf/config_file.h" +#include "conf/config_file.h" -@implementation RADirectoryItem -+ (RADirectoryItem*)directoryItemFromPath:(const char*)thePath -{ - RADirectoryItem* result = [RADirectoryItem new]; - result.path = [NSString stringWithUTF8String:thePath]; - - struct stat statbuf; - if (stat(thePath, &statbuf) == 0) - result.isDirectory = S_ISDIR(statbuf.st_mode); - - return result; -} +@interface RADirectoryItem : NSObject +@property (strong) NSString* path; +@property bool isDirectory; @end - -BOOL ra_ios_is_file(NSString* path) -{ - return [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:nil]; -} - -BOOL ra_ios_is_directory(NSString* path) -{ - BOOL result = NO; - [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&result]; - return result; -} - -static NSArray* ra_ios_list_directory(NSString* path) -{ - NSMutableArray* result = [NSMutableArray arrayWithCapacity:27]; - for (int i = 0; i < 28; i ++) - { - [result addObject:[NSMutableArray array]]; - } - - // Build list - char* cpath = malloc([path length] + sizeof(struct dirent)); - sprintf(cpath, "%s/", [path UTF8String]); - size_t cpath_end = strlen(cpath); - - DIR* dir = opendir(cpath); - if (!dir) - return result; - - for(struct dirent* item = readdir(dir); item; item = readdir(dir)) - { - if (strncmp(item->d_name, ".", 1) == 0) - continue; - - cpath[cpath_end] = 0; - strcat(cpath, item->d_name); - - RADirectoryItem* value = [RADirectoryItem directoryItemFromPath:cpath]; - - uint32_t section = isalpha(item->d_name[0]) ? (toupper(item->d_name[0]) - 'A') + 2 : 1; - section = value.isDirectory ? 0 : section; - [result[section] addObject:[RADirectoryItem directoryItemFromPath:cpath]]; - } - - closedir(dir); - free(cpath); - - // Sort - for (int i = 0; i < result.count; i ++) - [result[i] sortUsingComparator:^(RADirectoryItem* left, RADirectoryItem* right) - { - return (left.isDirectory != right.isDirectory) ? - (left.isDirectory ? -1 : 1) : - ([left.path caseInsensitiveCompare:right.path]); - }]; - - return result; -} +@implementation RADirectoryItem +@end @implementation RADirectoryList { - NSArray* _list; + NSMutableArray* _list; } + (id)directoryListAtBrowseRoot @@ -102,7 +36,7 @@ static NSArray* ra_ios_list_directory(NSString* path) NSString* rootPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; NSString* ragPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/RetroArchGames"]; - return [RADirectoryList directoryListForPath:ra_ios_is_directory(ragPath) ? ragPath : rootPath]; + return [RADirectoryList directoryListForPath:path_is_directory(ragPath.UTF8String) ? ragPath : rootPath]; } + (id)directoryListForPath:(NSString*)path @@ -114,17 +48,40 @@ static NSArray* ra_ios_list_directory(NSString* path) - (id)initWithPath:(NSString*)path { self = [super initWithStyle:UITableViewStylePlain]; + [self setTitle: [path lastPathComponent]]; - if (!ra_ios_is_directory(path)) + // Need one array per section + _list = [NSMutableArray arrayWithCapacity:28]; + for (int i = 0; i < 28; i ++) + [_list addObject:[NSMutableArray array]]; + + // List contents + struct string_list* contents = dir_list_new(path.UTF8String, 0, true); + + if (contents) { - [RetroArch_iOS displayErrorMessage:[NSString stringWithFormat:@"Browsed path is not a directory: %@", path]]; - _list = [NSArray array]; + dir_list_sort(contents, true); + + for (int i = 0; i < contents->size; i ++) + { + const char* basename = path_basename(contents->elems[i].data); + + if (basename[0] == '.') + continue; + + uint32_t section = isalpha(basename[0]) ? (toupper(basename[0]) - 'A') + 2 : 1; + section = contents->elems[i].attr.b ? 0 : section; + + RADirectoryItem* item = RADirectoryItem.new; + item.path = [NSString stringWithUTF8String:contents->elems[i].data]; + item.isDirectory = contents->elems[i].attr.b; + [_list[section] addObject:item]; + } + + dir_list_free(contents); } else - { - [self setTitle: [path lastPathComponent]]; - _list = ra_ios_list_directory(path); - } + [RetroArch_iOS displayErrorMessage:[NSString stringWithFormat:@"Browsed path is not a directory: %@", path]]; return self; } diff --git a/ios/RetroArch/main.m b/ios/RetroArch/main.m index a4af4450d0..562c57bfbc 100644 --- a/ios/RetroArch/main.m +++ b/ios/RetroArch/main.m @@ -24,6 +24,7 @@ #include "rarch_wrapper.h" #include "general.h" +#include "file.h" #include "frontend/menu/rmenu.h" #import "browser/browser.h" @@ -252,7 +253,14 @@ static void event_reload_config(void* userdata) self.system_directory = [NSString stringWithFormat:@"%@/.RetroArch", documentsPath]; self.systemConfigPath = [NSString stringWithFormat:@"%@/.RetroArch/frontend.cfg", documentsPath]; - mkdir([self.system_directory UTF8String], 0755); + + // Build system paths and test permissions + if (!path_is_directory(documentsPath.UTF8String) && mkdir(documentsPath.UTF8String, 0755)) + [RetroArch_iOS displayErrorMessage:[NSString stringWithFormat:@"Failed to create base directory: %@", documentsPath]]; + else if (!path_is_directory(self.system_directory.UTF8String) && mkdir(self.system_directory.UTF8String, 0755)) + [RetroArch_iOS displayErrorMessage:[NSString stringWithFormat:@"Failed to create system directory: %@", self.system_directory]]; + else if (access(self.system_directory.UTF8String, R_OK | W_OK | X_OK)) + [RetroArch_iOS displayErrorMessage:[NSString stringWithFormat:@"System directory has incorrect permissions: %@", self.system_directory]]; // Setup window self.delegate = self; @@ -344,8 +352,8 @@ static void event_reload_config(void* userdata) [self pushViewController:RAGameView.get animated:NO]; _isRunning = true; - const char* const sd = [[RetroArch_iOS get].system_directory UTF8String]; - const char* const cf = (ra_ios_is_file(_module.configPath)) ? [_module.configPath UTF8String] : 0; + const char* const sd = RetroArch_iOS.get.system_directory.UTF8String; + const char* const cf = (path_file_exists(_module.configPath.UTF8String)) ? [_module.configPath UTF8String] : 0; const char* const libretro = [_module.path UTF8String]; struct rarch_main_wrap* load_data = malloc(sizeof(struct rarch_main_wrap));