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