1 #include <TargetConditionals.h>
3 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
12 #include <sys/sysctl.h>
13 #include <System/sys/fsgetpath.h>
14 #include <hfs/hfs_fsctl.h>
15 #include <sys/mount.h>
16 #include <sys/param.h>
18 #include "hfs-tests.h"
19 #include "test-utils.h"
21 TEST(list_ids
, .run_as_root
= true)
31 } __attribute__((aligned(4), packed
)) attrs
[MAX_FILES
];
33 static char *path
[MAX_FILES
];
34 static int fd
[MAX_FILES
];
36 static uint32_t max_ids
= 1000000;
37 static uint32_t max_ids_per_iter
= 262144;
39 int run_list_ids(__unused test_ctx_t
*ctx
)
41 // The data partition needs to be HFS
44 assert(statfs("/private/var", &sfs
) == 0);
45 if (strcmp(sfs
.f_fstypename
, "hfs")) {
46 printf("list_ids needs hfs on the data partition.\n");
51 uint32_t *file_ids
= malloc(4 * max_ids
);
54 bzero(file_ids
, 4 * max_ids
);
56 struct listxattrid_cp listxattrid_file_ids
= {
57 .flags
= (LSXCP_PROT_CLASS_A
| LSXCP_PROT_CLASS_B
58 | LSXCP_PROT_CLASS_C
| LSXCP_UNROLLED_KEYS
),
62 listxattrid_file_ids
.count
= max_ids_per_iter
;
63 listxattrid_file_ids
.fileid
= file_ids
+ count
;
65 assert_no_err(fsctl("/private/var", HFSIOC_LISTXATTRID_CP
, &listxattrid_file_ids
, 0));
67 count
+= listxattrid_file_ids
.count
;
68 assert(count
< max_ids
);
69 } while (count
== max_ids_per_iter
);
71 void *buf
= malloc(1 KB
);
72 memset(buf
, 0x25, 1 KB
);
74 for (unsigned i
= 0; i
< MAX_FILES
; i
++) {
76 asprintf(&path
[i
], "/private/var/get-matched_listid.data.%u", getpid()+i
);
79 assert_with_errno((fd
[i
] = open(path
[i
], O_RDWR
| O_TRUNC
| O_CREAT
, 0666)) >= 0);
82 check_io(write(fd
[i
], buf
, 1 KB
), 1 KB
);
84 // Change file to class B
85 assert_no_err(fcntl(fd
[i
], F_SETPROTECTIONCLASS
, 2));
87 struct attrlist attrlist
= {
88 .bitmapcount
= ATTR_BIT_MAP_COUNT
,
89 .commonattr
= ATTR_CMN_FILEID
| ATTR_CMN_DATA_PROTECT_FLAGS
,
92 assert_no_err(fgetattrlist(fd
[i
], &attrlist
, &attrs
[i
], sizeof(attrs
), 0));
93 assert((attrs
[i
].dp_flags
& 0x1f) == 2);
97 bool release_build
= false;
99 if (fcntl(fd
[0], F_RECYCLE
)) {
100 assert_equal_int(errno
, ENOTTY
);
101 release_build
= true;
104 // HFS_KR_OP_SET_INFO doesn't run in releae build.
108 for (unsigned i
= 0; i
< MAX_FILES
; i
++) {
110 hfs_key_roll_args_t args
;
112 // Change the revision and os version
113 args
.api_version
= HFS_KR_API_LATEST_VERSION
;
114 args
.operation
= HFS_KR_OP_SET_INFO
;
115 args
.key_revision
= 0x0200;
116 args
.key_os_version
= CP_OS_VERS_PRE_71
;
117 assert_no_err(ffsctl(fd
[i
], HFSIOC_KEY_ROLL
, &args
, 0));
119 args
.operation
= HFS_KR_OP_STATUS
;
120 assert_no_err(ffsctl(fd
[i
], HFSIOC_KEY_ROLL
, &args
, 0));
122 assert(args
.done
== -1
123 && args
.key_revision
== 0x0200
124 && args
.key_os_version
== CP_OS_VERS_PRE_71
);
128 max_ids_per_iter
= 48;
130 bzero(file_ids
, 4 * max_ids
);
132 struct cp_listids list_file_ids
= {
133 .api_version
= CPLIDS_API_VERSION_1
,
134 .flags
= CPLID_MAX_OS_VERSION
| CPLID_PROT_CLASS_B
,
135 .max_key_os_version
= CP_OS_VERS_71
,
139 list_file_ids
.count
= max_ids_per_iter
;
140 list_file_ids
.file_ids
= file_ids
+ count
;
142 if (fsctl("/private/var", HFSIOC_CP_LIST_IDS
, &list_file_ids
, 0) < 0) {
143 assert_with_errno(errno
== EINTR
);
145 bzero(list_file_ids
.state
, sizeof(list_file_ids
.state
));
148 count
+= list_file_ids
.count
;
150 assert(count
< max_ids
);
152 } while (list_file_ids
.count
== max_ids_per_iter
);
154 assert(count
== MAX_FILES
);
156 statfs("/private/var", &sfs
);
158 for (i
= 0; i
< count
; i
++) {
159 char path_name
[PATH_MAX
];
161 if (fsgetpath(path_name
, sizeof(path
), &sfs
.f_fsid
,
162 (uint64_t)file_ids
[i
]) < 0) {
163 assert_with_errno(errno
== ENOENT
);
166 assert(file_ids
[i
] == attrs
[i
].file_id
);
174 for (i
= 0; i
< MAX_FILES
; i
++) {
175 assert_no_err(close(fd
[i
]));
185 #endif // (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)