]> git.saurik.com Git - apple/hfs.git/blob - livefiles_hfs_plugin/lf_hfs_vnode.c
hfs-556.41.1.tar.gz
[apple/hfs.git] / livefiles_hfs_plugin / lf_hfs_vnode.c
1 /* Copyright © 2017-2018 Apple Inc. All rights reserved.
2 *
3 * lf_hfs_vnode.c
4 * livefiles_hfs
5 *
6 * Created by Or Haimovich on 20/3/18.
7 */
8
9 #include "lf_hfs_vnode.h"
10 #include "lf_hfs_utils.h"
11 #include "lf_hfs_vfsutils.h"
12 #include "lf_hfs_generic_buf.h"
13 #include "lf_hfs_fileops_handler.h"
14 #include "lf_hfs_xattr.h"
15 #include <System/sys/decmpfs.h>
16
17 int VTtoUVFS_tab[16] =
18 {
19 VNON,
20 /* 1 - 5 */
21 UVFS_FA_TYPE_FILE, UVFS_FA_TYPE_DIR, VNON, VNON, UVFS_FA_TYPE_SYMLINK,
22 /* 6 - 10 */
23 VNON, VNON, VNON, VNON, VNON
24 };
25
26 enum vtype iftovt_tab[16] =
27 {
28 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
29 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
30 };
31
32 int uvfsToVtype_tab[4] =
33 {
34 VNON,VREG,VDIR,VLNK,
35 };
36
37 mode_t vttoif_tab[9] =
38 {
39 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
40 S_IFSOCK, S_IFIFO, S_IFMT,
41 };
42
43 errno_t vnode_initialize(uint32_t size, void *data, vnode_t *vpp)
44 {
45 memset(*vpp,0,sizeof(struct vnode));
46 (*vpp)->cnode = NULL;
47 assert(size == sizeof((*vpp)->sFSParams));
48 memcpy((void *) &(*vpp)->sFSParams,data,size);
49
50 if ((*vpp)->sFSParams.vnfs_vtype == VDIR)
51 {
52 (*vpp)->sExtraData.sDirData.uDirVersion = 1;
53 }
54 return 0;
55 }
56
57 errno_t vnode_create(uint32_t size, void *data, vnode_t *vpp)
58 {
59 *vpp = hfs_malloc(sizeof(struct vnode));
60 if (*vpp == NULL)
61 {
62 return ENOMEM;
63 }
64
65 return (vnode_initialize(size, data, vpp));
66 }
67
68 void vnode_rele(vnode_t vp)
69 {
70 if (vp) {
71 lf_hfs_generic_buf_cache_LockBufCache();
72 lf_hfs_generic_buf_cache_remove_vnode(vp);
73 lf_hfs_generic_buf_cache_UnLockBufCache();
74 hfs_free(vp);
75 }
76 vp = NULL;
77 }
78
79 mount_t vnode_mount(vnode_t vp)
80 {
81 return (vp->sFSParams.vnfs_mp);
82 }
83
84 int vnode_issystem(vnode_t vp)
85 {
86 return (vp->sFSParams.vnfs_marksystem);
87 }
88
89 int vnode_isreg(vnode_t vp)
90 {
91 return (vp->sFSParams.vnfs_vtype == VREG);
92 }
93
94 int vnode_isdir(vnode_t vp)
95 {
96 return (vp->sFSParams.vnfs_vtype == VDIR);
97 }
98
99 int vnode_islnk(vnode_t vp)
100 {
101 return (vp->sFSParams.vnfs_vtype == VLNK);
102 }
103
104 /*!
105 @function vnode_update_identity
106 case:
107 VNODE_UPDATE_PARENT: set parent.
108 VNODE_UPDATE_NAME: set name.
109 VNODE_UPDATE_CACHE: flush cache entries for hard links associated with this file.
110
111
112 */
113 void vnode_update_identity(vnode_t vp, vnode_t dvp, const char *name, int name_len, uint32_t name_hashval, int flags)
114 {
115 if (flags & VNODE_UPDATE_PARENT)
116 {
117 vp->sFSParams.vnfs_dvp = dvp;
118 }
119
120 if (flags & VNODE_UPDATE_NAME)
121 {
122 if (!vp->sFSParams.vnfs_cnp) {
123 vp->sFSParams.vnfs_cnp = hfs_malloc(sizeof(struct componentname));
124 if (vp->sFSParams.vnfs_cnp == NULL) {
125 LFHFS_LOG(LEVEL_ERROR, "vnode_update_identity: failed to malloc vnfs_cnp\n");
126 assert(0);
127 }
128 bzero(vp->sFSParams.vnfs_cnp, sizeof(struct componentname));
129 }
130 vp->sFSParams.vnfs_cnp->cn_namelen = name_len;
131 if (vp->sFSParams.vnfs_cnp->cn_nameptr) {
132 hfs_free(vp->sFSParams.vnfs_cnp->cn_nameptr);
133 vp->sFSParams.vnfs_cnp->cn_nameptr = NULL;
134 }
135 vp->sFSParams.vnfs_cnp->cn_nameptr = lf_hfs_utils_allocate_and_copy_string( (char*) name, name_len );
136 vp->sFSParams.vnfs_cnp->cn_hash = name_hashval;
137 }
138 }
139
140 void vnode_GetAttrInternal (vnode_t vp, UVFSFileAttributes *psOutAttr )
141 {
142 struct cnode *cp = VTOC(vp);
143 enum vtype v_type;
144
145 memset( psOutAttr, 0, sizeof(UVFSFileAttributes) );
146
147 psOutAttr->fa_validmask = VALID_OUT_ATTR_MASK;
148
149 psOutAttr->fa_gid = cp->c_gid;
150 psOutAttr->fa_uid = cp->c_uid;
151 psOutAttr->fa_mode = cp->c_mode & ALL_UVFS_MODES;
152
153 v_type = vp->sFSParams.vnfs_vtype;
154 psOutAttr->fa_type = VTOUVFS(v_type);
155
156 psOutAttr->fa_atime.tv_sec = cp->c_atime;
157 psOutAttr->fa_ctime.tv_sec = cp->c_ctime;
158 psOutAttr->fa_mtime.tv_sec = cp->c_mtime;
159 psOutAttr->fa_birthtime.tv_sec = cp->c_btime;
160
161 psOutAttr->fa_fileid = cp->c_fileid;
162 psOutAttr->fa_parentid = cp->c_parentcnid;
163 psOutAttr->fa_bsd_flags = cp->c_bsdflags;
164
165 if (v_type == VDIR)
166 {
167 psOutAttr->fa_allocsize = 0;
168 psOutAttr->fa_size = (cp->c_entries + 2) * AVERAGE_HFSDIRENTRY_SIZE;
169 psOutAttr->fa_nlink = cp->c_entries + 2;
170 }
171 else
172 {
173 if (psOutAttr->fa_bsd_flags & UF_COMPRESSED)
174 {
175 if (VNODE_IS_RSRC(vp))
176 {
177 psOutAttr->fa_allocsize = VTOF(vp)->ff_blocks * VTOHFS(vp)->blockSize;
178 psOutAttr->fa_size = VTOF(vp)->ff_size;
179 }
180 else
181 {
182 hfs_unlock(VTOC(vp));
183 void* data = NULL;
184 size_t attr_size;
185 int iErr = hfs_vnop_getxattr(vp, "com.apple.decmpfs", NULL, 0, &attr_size);
186 if (iErr != 0) {
187 goto fail;
188 }
189
190 if (attr_size < sizeof(decmpfs_disk_header) || attr_size > MAX_DECMPFS_XATTR_SIZE) {
191 iErr = EINVAL;
192 goto fail;
193 }
194 /* allocation includes space for the extra attr_size field of a compressed_header */
195 data = (char *) malloc(attr_size);
196 if (!data) {
197 iErr = ENOMEM;
198 goto fail;
199 }
200
201 /* read the xattr into our buffer, skipping over the attr_size field at the beginning */
202 size_t read_size;
203 iErr = hfs_vnop_getxattr(vp, "com.apple.decmpfs", data, attr_size, &read_size);
204 if (iErr != 0) {
205 goto fail;
206 }
207 if (read_size != attr_size) {
208 iErr = EINVAL;
209 goto fail;
210 }
211
212 decmpfs_header Hdr;
213 Hdr.attr_size = (uint32_t) attr_size;
214 Hdr.compression_magic = *((uint32_t*)data);
215 Hdr.compression_type = *((uint32_t*)(data + sizeof(uint32_t)));
216 Hdr.uncompressed_size = *((uint32_t*)(data + sizeof(uint64_t)));
217
218 fail:
219 if (iErr)
220 {
221 psOutAttr->fa_allocsize = VCTOF(vp, cp)->ff_blocks * VTOHFS(vp)->blockSize;
222 psOutAttr->fa_size = VCTOF(vp, cp)->ff_size;
223 }
224 else
225 {
226 psOutAttr->fa_allocsize = ROUND_UP(Hdr.uncompressed_size,VTOHFS(vp)->blockSize);
227 psOutAttr->fa_size = Hdr.uncompressed_size;
228 }
229
230 if (data) free(data);
231 hfs_lock(VTOC(vp), 0, 0);
232 }
233 }
234 else
235 {
236 psOutAttr->fa_allocsize = VCTOF(vp, cp)->ff_blocks * VTOHFS(vp)->blockSize;
237 psOutAttr->fa_size = VCTOF(vp, cp)->ff_size;
238 }
239 psOutAttr->fa_nlink = (cp->c_flag & C_HARDLINK)? cp->c_linkcount : 1;
240 }
241 }