]> git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/synthfs/synthfs_util.c
19ae21db90845c2ae889af5670aa0f049cf94580
[apple/xnu.git] / bsd / miscfs / synthfs / synthfs_util.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* Copyright (c) 1998, Apple Computer, Inc. All rights reserved. */
24 /*
25 * Change History:
26 *
27 * 17-Aug-1999 Pat Dirks New today.
28 *
29 */
30
31 #include <mach/mach_types.h>
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/file.h>
37 #include <sys/stat.h>
38 #include <sys/proc.h>
39 #include <sys/conf.h>
40 #include <sys/mount_internal.h>
41 #include <sys/vnode_internal.h>
42 #include <sys/malloc.h>
43 #include <sys/dirent.h>
44 #include <sys/namei.h>
45 #include <sys/attr.h>
46 #include <sys/time.h>
47 #include <sys/uio_internal.h>
48
49 #include <sys/vm.h>
50 #include <sys/errno.h>
51 #include <vfs/vfs_support.h>
52
53 #include "synthfs.h"
54
55 struct synthfs_direntry_head {
56 u_int32_t d_fileno; /* file number of entry */
57 u_int16_t d_reclen; /* length of this record */
58 u_int8_t d_type; /* file type, see below */
59 u_int8_t d_namlen; /* length of string in d_name */
60 };
61
62
63 #define PATHSEPARATOR '/'
64 #define ROOTDIRID 2
65
66
67 static int synthfs_insertnode(struct synthfsnode *newnode_sp, struct synthfsnode *parent_sp) {
68 struct timeval now;
69
70 DBG_ASSERT(parent_sp->s_type == SYNTHFS_DIRECTORY);
71
72 TAILQ_INSERT_TAIL(&parent_sp->s_u.d.d_subnodes, newnode_sp, s_sibling);
73 ++parent_sp->s_u.d.d_entrycount;
74 newnode_sp->s_parent = parent_sp;
75
76 parent_sp->s_nodeflags |= IN_CHANGE | IN_MODIFIED;
77 microtime(&now);
78 synthfs_update(STOV(parent_sp), &now, &now, 0);
79
80 return 0;
81 }
82
83
84
85 static int synthfs_newnode(mount_t mp, vnode_t dp, const char *name, unsigned long nodeid,
86 mode_t mode, __unused proc_t p, enum vtype vtype, vnode_t *vpp) {
87 int result;
88 struct synthfsnode *sp;
89 struct vnode *vp;
90 struct timeval now;
91 char *nodename;
92 struct vnode_fsparam vfsp;
93
94 MALLOC(sp, struct synthfsnode *, sizeof(struct synthfsnode), M_SYNTHFS, M_WAITOK);
95
96 if (name == NULL) {
97 MALLOC(nodename, char *, 1, M_TEMP, M_WAITOK);
98 nodename[0] = 0;
99 } else {
100 MALLOC(nodename, char *, strlen(name) + 1, M_TEMP, M_WAITOK);
101 strcpy(nodename, name);
102 };
103
104 /* Initialize the relevant synthfsnode fields: */
105 bzero(sp, sizeof(*sp));
106 sp->s_nodeid = nodeid;
107
108 /* Initialize all times from a consistent snapshot of the clock: */
109 microtime(&now);
110 sp->s_createtime = now;
111 sp->s_accesstime = now;
112 sp->s_modificationtime = now;
113 sp->s_changetime = now;
114 sp->s_name = nodename;
115 sp->s_mode = mode;
116
117
118 //bzero(&vfsp, sizeof(struct vnode_fsparam));
119 vfsp.vnfs_mp = mp;
120 vfsp.vnfs_vtype = vtype;
121 vfsp.vnfs_str = "synthfs";
122 vfsp.vnfs_dvp = 0;
123 vfsp.vnfs_fsnode = sp;
124 vfsp.vnfs_cnp = 0;
125 vfsp.vnfs_vops = synthfs_vnodeop_p;
126 vfsp.vnfs_rdev = 0;
127 vfsp.vnfs_filesize = 0;
128 vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
129 vfsp.vnfs_marksystem = 0;
130 vfsp.vnfs_markroot = 0;
131
132 result = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &vp);
133 if (result != 0) {
134 DBG_VOP(("getnewvnode failed with error code %d\n", result));
135 FREE(nodename, M_TEMP);
136 FREE(sp, M_TEMP);
137 return result;
138 }
139 vnode_ref(vp);
140
141 sp->s_vp = vp;
142
143 /* If there's a parent directory, update its subnode structures to insert this new node: */
144 if (dp) {
145 result = synthfs_insertnode(sp, VTOS(dp));
146 };
147
148 *vpp = vp;
149
150 return result;
151 }
152
153
154
155 int synthfs_remove_entry(struct vnode *vp) {
156 struct synthfsnode *sp = VTOS(vp);
157 struct synthfsnode *psp = sp->s_parent;
158 struct timeval now;
159
160 if (psp) {
161 TAILQ_REMOVE(&psp->s_u.d.d_subnodes, sp, s_sibling);
162 --psp->s_u.d.d_entrycount;
163
164 psp->s_nodeflags |= IN_CHANGE | IN_MODIFIED;
165 microtime(&now);
166 synthfs_update(STOV(psp), &now, &now, 0);
167 };
168
169 return 0;
170 }
171
172
173
174 int synthfs_move_rename_entry(struct vnode *source_vp, struct vnode *newparent_vp, char *new_name) {
175 struct synthfsnode *source_sp = VTOS(source_vp);
176 struct synthfsnode *parent_sp = VTOS(newparent_vp);
177 char *new_name_ptr;
178 int result = 0;
179
180 /* Unlink the entry from its current place: */
181 result = synthfs_remove_entry(source_vp);
182 if (result) goto err_exit;
183
184 /* Change the name as necessary: */
185 if (new_name) {
186 FREE(source_sp->s_name, M_TEMP);
187 MALLOC(new_name_ptr, char *, strlen(new_name) + 1, M_TEMP, M_WAITOK);
188 strcpy(new_name_ptr, new_name);
189 source_sp->s_name = new_name_ptr;
190 };
191
192 /* Insert the entry in its new home: */
193 result = synthfs_insertnode(source_sp, parent_sp);
194
195 err_exit:
196 return result;
197 }
198
199
200
201 int synthfs_new_directory(struct mount *mp, struct vnode *dp, const char *name, unsigned long nodeid, mode_t mode, struct proc *p, struct vnode **vpp) {
202 int result;
203 struct vnode *vp;
204 struct synthfsnode *sp;
205
206 result = synthfs_newnode(mp, dp, name, nodeid, mode, p, VDIR, &vp);
207 if (result) {
208 return result;
209 };
210 sp = VTOS(vp);
211 sp->s_linkcount = 2;
212
213 if (dp) {
214 ++VTOS(dp)->s_linkcount; /* Account for the [fictitious] ".." link */
215 };
216
217 /* Set up the directory-specific fields: */
218 sp->s_type = SYNTHFS_DIRECTORY;
219 sp->s_u.d.d_entrycount = 0; /* No entries in this directory yet */
220 TAILQ_INIT(&sp->s_u.d.d_subnodes); /* No subnodes of this directory yet */
221
222 *vpp = vp;
223
224 return 0;
225 }
226
227
228
229 int synthfs_remove_directory(struct vnode *vp) {
230 struct synthfsnode *sp = VTOS(vp);
231 struct synthfsnode *psp = sp->s_parent;
232
233 if (psp && (sp->s_type == SYNTHFS_DIRECTORY) && (psp != sp)) {
234 --psp->s_linkcount; /* account for the [fictitious] ".." link now removed */
235 };
236 vnode_rele(vp);
237
238 /* Do the standard cleanup involved in pruning an entry from the filesystem: */
239 return synthfs_remove_entry(vp); /* Do whatever standard cleanup is required */
240 }
241
242
243
244 int synthfs_new_symlink(
245 struct mount *mp,
246 struct vnode *dp,
247 const char *name,
248 unsigned long nodeid,
249 char *targetstring,
250 struct proc *p,
251 struct vnode **vpp) {
252
253 int result;
254 struct vnode *vp;
255 struct synthfsnode *sp;
256
257 result = synthfs_newnode(mp, dp, name, nodeid, 0, p, VLNK, &vp);
258 if (result) {
259 return result;
260 };
261 sp = VTOS(vp);
262 sp->s_linkcount = 1;
263
264 /* Set up the symlink-specific fields: */
265 sp->s_type = SYNTHFS_SYMLINK;
266 sp->s_u.s.s_length = strlen(targetstring);
267 MALLOC(sp->s_u.s.s_symlinktarget, char *, sp->s_u.s.s_length + 1, M_TEMP, M_WAITOK);
268 strcpy(sp->s_u.s.s_symlinktarget, targetstring);
269
270 *vpp = vp;
271
272 return 0;
273 }
274
275
276
277 int synthfs_remove_symlink(struct vnode *vp) {
278 struct synthfsnode *sp = VTOS(vp);
279
280 FREE(sp->s_u.s.s_symlinktarget, M_TEMP);
281 vnode_rele(vp);
282
283 /* Do the standard cleanup involved in pruning an entry from the filesystem: */
284 return synthfs_remove_entry(vp); /* Do whatever standard cleanup is required */
285 }
286
287
288
289
290
291
292 long synthfs_adddirentry(u_int32_t fileno, u_int8_t type, const char *name, struct uio *uio) {
293 struct synthfs_direntry_head direntry;
294 long namelength;
295 int padding;
296 long padtext = 0;
297 unsigned short direntrylength;
298
299 namelength = ((name == NULL) ? 0 : strlen(name) + 1);
300 padding = (4 - (namelength & 3)) & 3;
301 direntrylength = sizeof(struct synthfs_direntry_head) + namelength + padding;
302
303 direntry.d_fileno = fileno;
304 direntry.d_reclen = direntrylength;
305 direntry.d_type = type;
306 direntry.d_namlen = namelength;
307
308 if (uio_resid(uio) < direntry.d_reclen) {
309 direntrylength = 0;
310 } else {
311 uiomove((caddr_t)(&direntry), sizeof(direntry), uio);
312 if (name != NULL) {
313 uiomove((caddr_t)name, namelength, uio);
314 };
315 if (padding > 0) {
316 uiomove((caddr_t)&padtext, padding, uio);
317 };
318 };
319
320 return direntrylength;
321 }
322
323