]>
git.saurik.com Git - apple/xnu.git/blob - bsd/vfs/doc_tombstone.c
2 * Copyright (c) 2015 Apple 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@
29 // -- Document ID Tombstone Support --
32 #include <sys/resource.h>
33 #include <sys/signal.h>
34 #include <sys/vfs_context.h>
35 #include <sys/doc_tombstone.h>
36 #include <sys/vnode_internal.h>
37 #include <sys/fsevents.h>
38 #include <kern/thread.h>
39 #include <kern/kalloc.h>
43 // This function gets the doc_tombstone structure for the
44 // current thread. If the thread doesn't have one, the
45 // structure is allocated.
47 struct doc_tombstone
*
48 doc_tombstone_get(void)
51 ut
= get_bsdthread_info(current_thread());
53 if (ut
->t_tombstone
== NULL
) {
54 ut
->t_tombstone
= kalloc(sizeof(struct doc_tombstone
));
55 if (ut
->t_tombstone
) {
56 memset(ut
->t_tombstone
, 0, sizeof(struct doc_tombstone
));
60 return ut
->t_tombstone
;
64 // This routine clears out the current tombstone for the
65 // current thread and if necessary passes the doc-id of
66 // the tombstone on to the dst_cnode.
68 // The caller is responsible for generating the appropriate
72 doc_tombstone_clear(struct doc_tombstone
*ut
, vnode_t
*old_vpp
)
74 uint32_t old_id
= ut
->t_lastop_document_id
;
76 ut
->t_lastop_document_id
= 0;
77 ut
->t_lastop_parent
= NULL
;
78 ut
->t_lastop_parent_vid
= 0;
79 ut
->t_lastop_filename
[0] = '\0';
82 // If the lastop item is still the same and needs to be cleared,
83 // clear it. The following isn't ideal because the vnode might
84 // have been recycled.
88 if (old_id
&& ut
->t_lastop_item
89 && vnode_vid(ut
->t_lastop_item
) == ut
->t_lastop_item_vid
) {
90 int res
= vnode_get(ut
->t_lastop_item
);
92 // Need to check vid again
93 if (vnode_vid(ut
->t_lastop_item
) == ut
->t_lastop_item_vid
94 && !ISSET(ut
->t_lastop_item
->v_lflag
, VL_TERMINATE
)) {
95 *old_vpp
= ut
->t_lastop_item
;
97 vnode_put(ut
->t_lastop_item
);
103 // last, clear these now that we're all done
104 ut
->t_lastop_item
= NULL
;
105 ut
->t_lastop_fileid
= 0;
106 ut
->t_lastop_item_vid
= 0;
111 // This function is used to filter out operations on temp
112 // filenames. We have to filter out operations on certain
113 // temp filenames to work-around questionable application
114 // behavior from apps like Autocad that perform unusual
115 // sequences of file system operations for a "safe save".
117 doc_tombstone_should_ignore_name(const char *nameptr
, int len
)
120 len
= strlen(nameptr
);
123 if (strncmp(nameptr
, "atmp", 4) == 0
124 || (len
> 4 && strncmp(nameptr
+ len
- 4, ".bak", 4) == 0)
125 || (len
> 4 && strncmp(nameptr
+ len
- 4, ".tmp", 4) == 0)) {
133 // Decide if we need to save a tombstone or not. Normally we always
134 // save a tombstone - but if there already is one and the name we're
135 // given is an ignorable name, then we will not save a tombstone.
138 doc_tombstone_should_save(struct doc_tombstone
*ut
, struct vnode
*vp
,
139 struct componentname
*cnp
)
141 if (cnp
->cn_nameptr
== NULL
) {
145 if (ut
->t_lastop_document_id
&& ut
->t_lastop_item
== vp
146 && doc_tombstone_should_ignore_name(cnp
->cn_nameptr
, cnp
->cn_namelen
)) {
154 // This function saves a tombstone for the given vnode and name. The
155 // tombstone represents the parent directory and name where the document
156 // used to live and the document-id of that file. This info is recorded
157 // in the doc_tombstone structure hanging off the uthread (which assumes
158 // that all safe-save operations happen on the same thread).
160 // If later on the same parent/name combo comes back into existence then
161 // we'll preserve the doc-id from this vnode onto the new vnode.
163 // The caller is responsible for generating the appropriate
167 doc_tombstone_save(struct vnode
*dvp
, struct vnode
*vp
,
168 struct componentname
*cnp
, uint64_t doc_id
,
171 struct doc_tombstone
*ut
;
172 ut
= doc_tombstone_get();
174 ut
->t_lastop_parent
= dvp
;
175 ut
->t_lastop_parent_vid
= vnode_vid(dvp
);
176 ut
->t_lastop_fileid
= file_id
;
177 ut
->t_lastop_item
= vp
;
178 ut
->t_lastop_item_vid
= vp
? vnode_vid(vp
) : 0;
179 ut
->t_lastop_document_id
= doc_id
;
181 strlcpy((char *)&ut
->t_lastop_filename
[0], cnp
->cn_nameptr
, sizeof(ut
->t_lastop_filename
));