ファイルの一覧を取得する
NSFileManagerの-enumeratorAtPath:を呼ぶと、特定ディレクトリの下を深さ優先でトラバースするNSDirectoryEnumeratorオブジェクトを返してくれるので、それで全ファイルエントリを取得出来るようだ。
但し、iTunesで買ったアプリなどは見えない*1。他にも見えないファイルがあるようだが、パーミッションの問題ではないようだ。別の方法で見せないようにしているっぽい。
/* CLANG_ENABLE_OBJC_ARC = YES */ #define TYPE_CHAR(fileType) (\ fileType == NSFileTypeDirectory ? 'd' \ : fileType == NSFileTypeSymbolicLink ? 'l' \ : fileType == NSFileTypeSocket ? 's' \ : fileType == NSFileTypeCharacterSpecial ? 'c' \ : fileType == NSFileTypeBlockSpecial ? 'b' \ : fileType == NSFileTypeUnknown ? '?' \ : '-' \ ) #define WHO_OWNER 2 #define WHO_GROUP 1 #define WHO_OTHER 0 /* non-zero if the file is readable */ #define READABLE(mode, who) (mode >> (who * 3 + 2) & 1) /* non-zero if the file is writable */ #define WRITABLE(mode, who) (mode >> (who * 3 + 1) & 1) /* non-zero if the file is executable or the directory is searchable */ #define EXECUTABLE(mode, who) (mode >> (who * 3 + 0) & 1) /* non-zero if set-x-ID or sticky bit is set */ #define SBIT_SET(mode, who) (mode >> (who + 9) & 1) #define SBIT_CHAR(mode, who) (\ who == WHO_OTHER \ ? (EXECUTABLE(mode, who) ? 't' : 'T') \ : (EXECUTABLE(mode, who) ? 's' : 'S') \ )\ #define MODE_CHARS(mode, who) \ READABLE(mode, who) ? 'r' :'-', \ WRITABLE(mode, who) ? 'w' :'-', \ SBIT_SET(mode, who) \ ? SBIT_CHAR(mode, who) \ : EXECUTABLE(mode, who) ? 'x' :'-' void show_files(NSString *directoryPath) { NSFileManager *fileManager = [NSFileManager defaultManager]; NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"MM dd HH:mm:ss yyyy"]; NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:directoryPath]; NSString *filePath; while (filePath = [enumerator nextObject]) { NSString *fullPath = [directoryPath stringByAppendingPathComponent:filePath]; NSDictionary *attrs = [enumerator fileAttributes]; NSString *fileType = [attrs objectForKey:NSFileType]; short mode = [[attrs objectForKey:NSFilePosixPermissions] shortValue]; NSString *owner = [attrs objectForKey:NSFileOwnerAccountName]; NSString *group = [attrs objectForKey:NSFileGroupOwnerAccountName]; NSDate *modificationDate = [attrs objectForKey:NSFileModificationDate]; unsigned long long fileSize = [[attrs objectForKey:NSFileSize] unsignedLongLongValue]; printf("%c" "%c%c%c" "%c%c%c" "%c%c%c" " %-8s %-8s %10qu %s %s\n", TYPE_CHAR(fileType), MODE_CHARS(mode, WHO_OWNER), MODE_CHARS(mode, WHO_GROUP), MODE_CHARS(mode, WHO_OTHER), [owner UTF8String], [group UTF8String], fileSize, [[dateFormat stringFromDate:modificationDate] UTF8String], [fullPath fileSystemRepresentation]); } }
show_files(@"/Developer/usr/bin/")してみた。
-rwxrwxr-x root admin 14496 02 02 16:20:17 2012 /Developer/usr/bin/chudRemoteCtrl -rwxrwxr-x root admin 152032 08 10 14:05:50 2011 /Developer/usr/bin/debugserver -rwxrwxr-x root admin 20176 02 02 16:20:33 2012 /Developer/usr/bin/hwprefs -rwxrwxr-x root admin 106016 01 16 12:09:06 2012 /Developer/usr/bin/reg -rwxrwxr-x root admin 18064 02 05 07:10:09 2012 /Developer/usr/bin/ScreenShotr -rwxrwxr-x root admin 117360 02 02 16:20:29 2012 /Developer/usr/bin/shark
他のディレクトリも含め、setuidしてるファイルは見つからなかった。
ソケットやシンボリックリンクはそれなりに見つかった。
拡張属性を調べるには、xattr.hにある関数を使えば良いっぽい。
#include <sys/types.h> #include <sys/xattr.h> ... ssize_t bufsize = listxattr([fullPath fileSystemRepresentation], NULL, 0,0); if (bufsize > 0){ char *buf = malloc(bufsize); listxattr([fullPath fileSystemRepresentation], buf, bufsize,0); char *ptr = buf; while(ptr < buf + bufsize){ ssize_t attrsize = getxattr([fullPath fileSystemRepresentation], ptr, NULL, 0, 0, 0); printf("\t%s\t%ld\n", ptr, attrsize); ptr += strlen(ptr) + 1; } free(buf); } ...
拡張属性が付いているファイルは一つしか見つからなかった。
-rw-r--r-- mobile mobile 5662 01 18 13:58:01 2012 /private/var/mobile/Media/PhotoData/MISC/PreviewWellImage.tiff com.apple.assetsd.thumbnailCameraPreviewImageAssetID 58
ファイルの中身は普通にFoundationのクラスでアクセス出来る。
NSData *data = [NSData dataWithContentsOfFile:@"/Developer/usr/bin/debugserver"]; NSLog(@"data = %@", data);
適当に一つiPad2からLion上に持って来てotoolで中身をみたら、ARM_V7用バイナリだった。
daphne:tmp terazzo$ otool -h debugserver debugserver: Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags 0xfeedface 12 9 0x00 2 19 2000 0x00210085
/usr/include/mach/machine.h によると
#define CPU_TYPE_ARM ((cpu_type_t) 12) #define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9)
追記: パーミッションのとこのAssert
ちょっと書いてた。関数の中から呼ぶときはNSAssertじゃなくてNSCAssertを使う。
#define ASSERT_MODE(mode, who, str) \ NSCAssert2(([[NSString stringWithFormat:@"%c%c%c", MODE_CHARS(mode, who)] isEqualToString:str]), \ @"'%@' expected but was '%@'", str, ([NSString stringWithFormat:@"%c%c%c", MODE_CHARS(mode, who)])) void assert_mode() { ASSERT_MODE(00000, WHO_OWNER, @"---"); ASSERT_MODE(00100, WHO_OWNER, @"--x"); ASSERT_MODE(00200, WHO_OWNER, @"-w-"); ASSERT_MODE(00300, WHO_OWNER, @"-wx"); ASSERT_MODE(00400, WHO_OWNER, @"r--"); ASSERT_MODE(00500, WHO_OWNER, @"r-x"); ASSERT_MODE(00600, WHO_OWNER, @"rw-"); ASSERT_MODE(00700, WHO_OWNER, @"rwx"); ASSERT_MODE(04000, WHO_OWNER, @"--S"); ASSERT_MODE(04100, WHO_OWNER, @"--s"); ASSERT_MODE(04200, WHO_OWNER, @"-wS"); ASSERT_MODE(04300, WHO_OWNER, @"-ws"); ASSERT_MODE(04400, WHO_OWNER, @"r-S"); ASSERT_MODE(04500, WHO_OWNER, @"r-s"); ASSERT_MODE(04600, WHO_OWNER, @"rwS"); ASSERT_MODE(04700, WHO_OWNER, @"rws"); ASSERT_MODE(01000, WHO_OTHER, @"--T"); ASSERT_MODE(01001, WHO_OTHER, @"--t"); ASSERT_MODE(01002, WHO_OTHER, @"-wT"); ASSERT_MODE(01003, WHO_OTHER, @"-wt"); ASSERT_MODE(01004, WHO_OTHER, @"r-T"); ASSERT_MODE(01005, WHO_OTHER, @"r-t"); ASSERT_MODE(01006, WHO_OTHER, @"rwT"); ASSERT_MODE(01007, WHO_OTHER, @"rwt"); }
追記2: 見えないディレクトリ
readdirで存在は確認できるがstatするとEPERMが戻ってくる。サンドボックス外のディレクトリについてはそういう風になるようだ。
#include <sys/param.h> #include <sys/stat.h> #include <dirent.h> ... const char base_dir[] = "/var/mobile/Applications/"; DIR *dir = opendir(base_dir); if (dir) { char path[MAXPATHLEN + 1]; struct dirent *dirent; struct stat st; while ((dirent = readdir(dir)) != NULL) { if (strlen(base_dir) + strlen(dirent->d_name) > MAXPATHLEN) continue; if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) continue; strcpy(path, base_dir); strcat(path, dirent->d_name); printf("file: \t%s\n", dirent->d_name); if (stat(path, &st) == -1) { perror("\t*** stat failed"); continue; } printf("\tmode:%0.6o\n", st.st_mode); } closedir(dir); }
file: 4335AC47-9753-4D5E-BF9F-52507E510B8C *** stat failed: Operation not permitted file: AD45441A-D37B-4B6A-8A46-3DEC149E0C54 *** stat failed: Operation not permitted file: BCAB6052-D9F7-4F52-9496-5F102EDC93B0 mode:040755
一番下の奴はこのプログラム自体を動かしているアプリケーションなので見えている。