2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1998, Apple Computer, Inc. All rights reserved. */
32 * 17-Aug-1999 Pat Dirks New today.
36 #include <mach/mach_types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
45 #include <sys/mount_internal.h>
46 #include <sys/vnode_internal.h>
47 #include <sys/malloc.h>
48 #include <sys/dirent.h>
49 #include <sys/namei.h>
52 #include <sys/uio_internal.h>
55 #include <sys/errno.h>
56 #include <vfs/vfs_support.h>
60 struct 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 */
68 #define PATHSEPARATOR '/'
72 static int synthfs_insertnode(struct synthfsnode
*newnode_sp
, struct synthfsnode
*parent_sp
) {
75 DBG_ASSERT(parent_sp
->s_type
== SYNTHFS_DIRECTORY
);
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
;
81 parent_sp
->s_nodeflags
|= IN_CHANGE
| IN_MODIFIED
;
83 synthfs_update(STOV(parent_sp
), &now
, &now
, 0);
91 synthfs_newnode(mount_t mp
, vnode_t dp
, const char *name
, unsigned long nodeid
,
92 mode_t mode
, __unused proc_t p
, enum vtype vtype
, vnode_t
*vpp
)
95 struct synthfsnode
*sp
;
99 struct vnode_fsparam vfsp
;
101 MALLOC(sp
, struct synthfsnode
*, sizeof(struct synthfsnode
), M_SYNTHFS
, M_WAITOK
);
104 MALLOC(nodename
, char *, 1, M_TEMP
, M_WAITOK
);
107 MALLOC(nodename
, char *, strlen(name
) + 1, M_TEMP
, M_WAITOK
);
108 strlcpy(nodename
, name
, strlen(name
) + 1);
111 /* Initialize the relevant synthfsnode fields: */
112 bzero(sp
, sizeof(*sp
));
113 sp
->s_nodeid
= nodeid
;
115 /* Initialize all times from a consistent snapshot of the clock: */
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
;
125 //bzero(&vfsp, sizeof(struct vnode_fsparam));
127 vfsp
.vnfs_vtype
= vtype
;
128 vfsp
.vnfs_str
= "synthfs";
130 vfsp
.vnfs_fsnode
= sp
;
132 vfsp
.vnfs_vops
= synthfs_vnodeop_p
;
134 vfsp
.vnfs_filesize
= 0;
135 vfsp
.vnfs_flags
= VNFS_NOCACHE
| VNFS_CANTCACHE
;
136 vfsp
.vnfs_marksystem
= 0;
137 vfsp
.vnfs_markroot
= 0;
139 result
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &vfsp
, &vp
);
141 DBG_VOP(("getnewvnode failed with error code %d\n", result
));
142 FREE(nodename
, M_TEMP
);
150 /* If there's a parent directory, update its subnode structures to insert this new node: */
152 result
= synthfs_insertnode(sp
, VTOS(dp
));
162 int synthfs_remove_entry(struct vnode
*vp
) {
163 struct synthfsnode
*sp
= VTOS(vp
);
164 struct synthfsnode
*psp
= sp
->s_parent
;
168 TAILQ_REMOVE(&psp
->s_u
.d
.d_subnodes
, sp
, s_sibling
);
169 --psp
->s_u
.d
.d_entrycount
;
171 psp
->s_nodeflags
|= IN_CHANGE
| IN_MODIFIED
;
173 synthfs_update(STOV(psp
), &now
, &now
, 0);
181 int 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
);
187 /* Unlink the entry from its current place: */
188 result
= synthfs_remove_entry(source_vp
);
189 if (result
) goto err_exit
;
191 /* Change the name as necessary: */
193 FREE(source_sp
->s_name
, M_TEMP
);
194 MALLOC(new_name_ptr
, char *, strlen(new_name
) + 1, M_TEMP
, M_WAITOK
);
195 strlcpy(new_name_ptr
, new_name
, strlen(new_name
) + 1);
196 source_sp
->s_name
= new_name_ptr
;
199 /* Insert the entry in its new home: */
200 result
= synthfs_insertnode(source_sp
, parent_sp
);
208 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
) {
211 struct synthfsnode
*sp
;
213 result
= synthfs_newnode(mp
, dp
, name
, nodeid
, mode
, p
, VDIR
, &vp
);
221 ++VTOS(dp
)->s_linkcount
; /* Account for the [fictitious] ".." link */
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 */
236 int synthfs_remove_directory(struct vnode
*vp
) {
237 struct synthfsnode
*sp
= VTOS(vp
);
238 struct synthfsnode
*psp
= sp
->s_parent
;
240 if (psp
&& (sp
->s_type
== SYNTHFS_DIRECTORY
) && (psp
!= sp
)) {
241 --psp
->s_linkcount
; /* account for the [fictitious] ".." link now removed */
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 */
256 unsigned long nodeid
,
263 struct synthfsnode
*sp
;
265 result
= synthfs_newnode(mp
, dp
, name
, nodeid
, 0, p
, VLNK
, &vp
);
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,
276 strlcpy(sp
->s_u
.s
.s_symlinktarget
, targetstring
,
277 sp
->s_u
.s
.s_lenghth
+ 1);
286 int synthfs_remove_symlink(struct vnode
*vp
) {
287 struct synthfsnode
*sp
= VTOS(vp
);
289 FREE(sp
->s_u
.s
.s_symlinktarget
, M_TEMP
);
292 /* Do the standard cleanup involved in pruning an entry from the filesystem: */
293 return synthfs_remove_entry(vp
); /* Do whatever standard cleanup is required */
301 long synthfs_adddirentry(u_int32_t fileno
, u_int8_t type
, const char *name
, struct uio
*uio
) {
302 struct synthfs_direntry_head direntry
;
306 unsigned short direntrylength
;
308 namelength
= ((name
== NULL
) ? 0 : strlen(name
) + 1);
309 padding
= (4 - (namelength
& 3)) & 3;
310 direntrylength
= sizeof(struct synthfs_direntry_head
) + namelength
+ padding
;
312 direntry
.d_fileno
= fileno
;
313 direntry
.d_reclen
= direntrylength
;
314 direntry
.d_type
= type
;
315 direntry
.d_namlen
= namelength
;
317 if (uio_resid(uio
) < direntry
.d_reclen
) {
320 uiomove((caddr_t
)(&direntry
), sizeof(direntry
), uio
);
322 uiomove((caddr_t
)name
, namelength
, uio
);
325 uiomove((caddr_t
)&padtext
, padding
, uio
);
329 return direntrylength
;