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