]> git.saurik.com Git - apple/hfs.git/blob - tests/cases/test-list-ids.c
hfs-522.0.9.tar.gz
[apple/hfs.git] / tests / cases / test-list-ids.c
1 #include <TargetConditionals.h>
2
3 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
4
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <sys/mman.h>
9 #include <string.h>
10 #include <sys/attr.h>
11 #include <sys/stat.h>
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>
17
18 #include "hfs-tests.h"
19 #include "test-utils.h"
20
21 TEST(list_ids, .run_as_root = true)
22
23 #define MAX_FILES 100
24 #define KB *1024
25 #define F_RECYCLE 84
26
27 static struct attrs {
28 uint32_t len;
29 uint64_t file_id;
30 uint32_t dp_flags;
31 } __attribute__((aligned(4), packed)) attrs[MAX_FILES];
32
33 static char *path[MAX_FILES];
34 static int fd[MAX_FILES];
35
36 static uint32_t max_ids = 1000000;
37 static uint32_t max_ids_per_iter = 262144;
38
39 int run_list_ids(__unused test_ctx_t *ctx)
40 {
41 // The data partition needs to be HFS
42 struct statfs sfs;
43
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");
47 return 0;
48 }
49
50 unsigned i;
51 uint32_t *file_ids = malloc(4 * max_ids);
52 uint32_t count = 0;
53
54 bzero(file_ids, 4 * max_ids);
55
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),
59 };
60
61 do {
62 listxattrid_file_ids.count = max_ids_per_iter;
63 listxattrid_file_ids.fileid = file_ids + count;
64
65 assert_no_err(fsctl("/private/var", HFSIOC_LISTXATTRID_CP, &listxattrid_file_ids, 0));
66
67 count += listxattrid_file_ids.count;
68 assert(count < max_ids);
69 } while (count == max_ids_per_iter);
70
71 void *buf = malloc(1 KB);
72 memset(buf, 0x25, 1 KB);
73
74 for (unsigned i = 0; i < MAX_FILES; i ++) {
75
76 asprintf(&path[i], "/private/var/get-matched_listid.data.%u", getpid()+i);
77 unlink(path[i]);
78
79 assert_with_errno((fd[i] = open(path[i], O_RDWR | O_TRUNC | O_CREAT, 0666)) >= 0);
80
81 // Write 1 kB
82 check_io(write(fd[i], buf, 1 KB), 1 KB);
83
84 // Change file to class B
85 assert_no_err(fcntl(fd[i], F_SETPROTECTIONCLASS, 2));
86
87 struct attrlist attrlist = {
88 .bitmapcount = ATTR_BIT_MAP_COUNT,
89 .commonattr = ATTR_CMN_FILEID | ATTR_CMN_DATA_PROTECT_FLAGS,
90 };
91
92 assert_no_err(fgetattrlist(fd[i], &attrlist, &attrs[i], sizeof(attrs), 0));
93 assert((attrs[i].dp_flags & 0x1f) == 2);
94
95 }
96
97 bool release_build = false;
98
99 if (fcntl(fd[0], F_RECYCLE)) {
100 assert_equal_int(errno, ENOTTY);
101 release_build = true;
102 }
103
104 // HFS_KR_OP_SET_INFO doesn't run in releae build.
105 if (release_build)
106 goto exit;
107
108 for (unsigned i = 0; i < MAX_FILES; i ++) {
109
110 hfs_key_roll_args_t args;
111
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));
118
119 args.operation = HFS_KR_OP_STATUS;
120 assert_no_err(ffsctl(fd[i], HFSIOC_KEY_ROLL, &args, 0));
121
122 assert(args.done == -1
123 && args.key_revision == 0x0200
124 && args.key_os_version == CP_OS_VERS_PRE_71);
125
126 }
127
128 max_ids_per_iter = 48;
129 count = 0;
130 bzero(file_ids, 4 * max_ids);
131
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,
136 };
137
138 do {
139 list_file_ids.count = max_ids_per_iter;
140 list_file_ids.file_ids = file_ids + count;
141
142 if (fsctl("/private/var", HFSIOC_CP_LIST_IDS, &list_file_ids, 0) < 0) {
143 assert_with_errno(errno == EINTR);
144 count = 0;
145 bzero(list_file_ids.state, sizeof(list_file_ids.state));
146 continue;
147 }
148 count += list_file_ids.count;
149
150 assert(count < max_ids);
151
152 } while (list_file_ids.count == max_ids_per_iter);
153
154 assert(count == MAX_FILES);
155
156 statfs("/private/var", &sfs);
157
158 for (i = 0; i < count; i++) {
159 char path_name[PATH_MAX];
160
161 if (fsgetpath(path_name, sizeof(path), &sfs.f_fsid,
162 (uint64_t)file_ids[i]) < 0) {
163 assert_with_errno(errno == ENOENT);
164 continue;
165 }
166 assert(file_ids[i] == attrs[i].file_id);
167 }
168
169 exit:
170
171 free(buf);
172 free(file_ids);
173
174 for (i = 0; i < MAX_FILES; i++) {
175 assert_no_err(close(fd[i]));
176 if (path[i]) {
177 unlink(path[i]);
178 free(path[i]);
179 }
180 }
181
182 return 0;
183 }
184
185 #endif // (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)