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