]>
Commit | Line | Data |
---|---|---|
558d2836 A |
1 | // |
2 | // test-getattrlist.c | |
3 | // hfs | |
4 | // | |
5 | // Created by Chris Suter on 8/21/15. | |
6 | // | |
7 | // | |
8 | ||
9 | #import <TargetConditionals.h> | |
10 | #include <fcntl.h> | |
11 | #include <sys/attr.h> | |
12 | #include <unistd.h> | |
13 | #include <sys/mount.h> | |
14 | #include <sys/kauth.h> | |
15 | #include <sys/param.h> | |
16 | ||
17 | #include "hfs-tests.h" | |
18 | #include "test-utils.h" | |
19 | #include "disk-image.h" | |
20 | ||
21 | ||
22 | ||
23 | TEST(getattrlist) | |
24 | ||
25 | #define TEST_FILE_NAME "getattrlist-test.file" | |
26 | ||
27 | int run_getattrlist(__unused test_ctx_t *ctx) | |
28 | { | |
29 | disk_image_t *di = NULL; | |
30 | const char *tstdir; | |
31 | bool hfs_root = true; //true until proven otherwise. | |
32 | ||
33 | #if TARGET_OS_EMBEDDED | |
34 | struct statfs sfs; | |
35 | ||
36 | assert(statfs("/tmp", &sfs) == 0); | |
37 | if (strcmp(sfs.f_fstypename, "hfs")) { | |
38 | hfs_root = false; | |
39 | di = disk_image_get(); | |
40 | tstdir = di->mount_point; | |
41 | } else { | |
42 | tstdir = "/tmp"; | |
43 | } | |
44 | #else // !TARGET_OS_EMBEDDED | |
45 | di = disk_image_get(); | |
46 | tstdir = di->mount_point; | |
47 | #endif | |
48 | ||
49 | char *file; | |
50 | asprintf(&file, "%s/getattrlist-test.file", tstdir); | |
51 | ||
52 | unlink(file); | |
53 | int fd = open_dprotected_np(file, O_RDWR | O_CREAT, 3, 0, 0666); | |
54 | ||
55 | assert_with_errno(fd >= 0); | |
56 | ||
57 | struct attrlist al = { | |
58 | .bitmapcount = ATTR_BIT_MAP_COUNT, | |
59 | .commonattr = ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | |
60 | | ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | |
61 | | ATTR_CMN_OBJPERMANENTID | ATTR_CMN_PAROBJID | ATTR_CMN_SCRIPT | |
62 | | ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | |
63 | | ATTR_CMN_ACCTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO | |
64 | | ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | |
65 | | ATTR_CMN_FLAGS | ATTR_CMN_GEN_COUNT | ATTR_CMN_DOCUMENT_ID | |
66 | | ATTR_CMN_USERACCESS | ATTR_CMN_EXTENDED_SECURITY | |
67 | | ATTR_CMN_UUID | ATTR_CMN_GRPUUID | ATTR_CMN_FILEID | |
68 | | ATTR_CMN_PARENTID | ATTR_CMN_FULLPATH | ATTR_CMN_ADDEDTIME | |
69 | | ATTR_CMN_DATA_PROTECT_FLAGS | ATTR_CMN_RETURNED_ATTRS, | |
70 | }; | |
71 | ||
72 | #pragma pack(push, 4) | |
73 | struct { | |
74 | uint32_t len; | |
75 | attribute_set_t returned_attrs; | |
76 | struct attrreference name; | |
77 | dev_t devid; | |
78 | fsid_t fsid; | |
79 | fsobj_type_t obj_type; | |
80 | fsobj_tag_t obj_tag; | |
81 | fsobj_id_t obj_id; | |
82 | fsobj_id_t obj_perm_id; | |
83 | fsobj_id_t par_obj_id; | |
84 | text_encoding_t encoding; | |
85 | struct timespec cr_time, mod_time, chg_time, acc_time, backup_time; | |
86 | uint8_t finder_info[32]; | |
87 | uid_t owner; | |
88 | gid_t group; | |
89 | uint32_t access_mask; | |
90 | uint32_t flags; | |
91 | uint32_t gen_count; | |
92 | uint32_t doc_id; | |
93 | uint32_t access; | |
94 | struct attrreference ext_security; | |
95 | guid_t guid; | |
96 | guid_t grp_uuid; | |
97 | uint64_t file_id; | |
98 | uint64_t parent_id; | |
99 | struct attrreference full_path; | |
100 | struct timespec added_time; | |
101 | uint32_t protection_class; | |
102 | uint8_t extra[1024]; | |
103 | } attrs; | |
104 | #pragma pack(pop) | |
105 | ||
106 | assert_no_err(fgetattrlist(fd, &al, &attrs, sizeof(attrs), | |
107 | FSOPT_ATTR_CMN_EXTENDED | FSOPT_PACK_INVAL_ATTRS)); | |
108 | ||
109 | uint32_t expected = al.commonattr ^ ATTR_CMN_EXTENDED_SECURITY; | |
110 | ||
111 | #if TARGET_OS_EMBEDDED | |
112 | if (hfs_root == true) { | |
113 | assert(attrs.protection_class == 3); | |
114 | } | |
115 | #else | |
116 | expected ^= ATTR_CMN_DATA_PROTECT_FLAGS; | |
117 | assert(attrs.protection_class == 0); | |
118 | #endif | |
119 | ||
120 | assert_equal_int(attrs.returned_attrs.commonattr, expected); | |
121 | ||
122 | // Just check a few things, not everything... | |
123 | ||
124 | assert(!strcmp((char *)&attrs.name + attrs.name.attr_dataoffset, | |
125 | TEST_FILE_NAME)); | |
126 | assert(strlen(TEST_FILE_NAME) + 1 == attrs.name.attr_length); | |
127 | ||
128 | char path[PATH_MAX]; | |
129 | assert(!strcmp((char *)&attrs.full_path + attrs.full_path.attr_dataoffset, | |
130 | realpath(file, path))); | |
131 | assert(strlen(path) + 1 == attrs.full_path.attr_length); | |
132 | ||
133 | time_t t = time(NULL); | |
134 | ||
135 | assert(attrs.cr_time.tv_sec > t - 5); | |
136 | assert(attrs.mod_time.tv_sec > t - 5); | |
137 | assert(attrs.chg_time.tv_sec > t - 5); | |
138 | assert(attrs.acc_time.tv_sec > t - 5); | |
139 | assert(attrs.backup_time.tv_sec == 0); | |
140 | assert(attrs.added_time.tv_sec > t - 5); | |
141 | ||
142 | if (hfs_root) { | |
143 | struct statfs sfs2; | |
144 | assert(statfs("/bin", &sfs2) == 0); | |
145 | assert(strcmp(sfs2.f_fstypename, "hfs") == 0); | |
146 | ||
147 | // Check a file on the system partition (this only valid if root == hfs) | |
148 | assert_no_err(getattrlist("/bin/sh", &al, &attrs, sizeof(attrs), | |
149 | FSOPT_ATTR_CMN_EXTENDED | FSOPT_PACK_INVAL_ATTRS)); | |
150 | ||
151 | assert(attrs.returned_attrs.commonattr == expected); | |
152 | assert(attrs.protection_class == 0); | |
153 | ||
154 | assert(!strcmp((char *)&attrs.name + attrs.name.attr_dataoffset, "sh")); | |
155 | assert(attrs.name.attr_length == 3); | |
156 | ||
157 | assert(!strcmp((char *)&attrs.full_path + attrs.full_path.attr_dataoffset, | |
158 | "/bin/sh")); | |
159 | assert(attrs.full_path.attr_length == 8); | |
160 | } | |
161 | ||
162 | assert_no_err(close(fd)); | |
163 | assert_no_err(unlink(file)); | |
164 | free(file); | |
165 | ||
166 | return 0; | |
167 | } |