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