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.
30 * File: bsd/kern/kern_symfile.c
35 #include <mach/vm_param.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/signalvar.h>
40 #include <sys/resourcevar.h>
41 #include <sys/namei.h>
42 #include <sys/vnode_internal.h>
43 #include <sys/proc_internal.h>
44 #include <sys/kauth.h>
45 #include <sys/timeb.h>
46 #include <sys/times.h>
48 #include <sys/file_internal.h>
50 #include <sys/kernel.h>
55 #include <mach-o/loader.h>
56 #include <mach-o/nlist.h>
58 #include <kern/kalloc.h>
59 #include <vm/vm_kern.h>
60 #include <pexpert/pexpert.h>
61 #include <IOKit/IOHibernatePrivate.h>
63 /* This function is called from kern_sysctl in the current process context;
64 * it is exported with the System6.0.exports, but this appears to be a legacy
65 * export, as there are no internal consumers.
68 get_kernel_symfile(__unused proc_t p
, __unused
char const **symfile
)
73 struct kern_direct_file_io_ref_t
80 static int file_ioctl(void * p1
, void * p2
, int theIoctl
, caddr_t result
)
82 dev_t device
= (dev_t
) p1
;
84 return ((*bdevsw
[major(device
)].d_ioctl
)
85 (device
, theIoctl
, result
, S_IFBLK
, p2
));
88 static int device_ioctl(void * p1
, __unused
void * p2
, int theIoctl
, caddr_t result
)
90 return (VNOP_IOCTL(p1
, theIoctl
, result
, 0, p2
));
93 struct kern_direct_file_io_ref_t
*
94 kern_open_file_for_direct_io(const char * name
,
95 kern_get_file_extents_callback_t callback
,
97 dev_t
* device_result
,
98 uint64_t * partitionbase_result
,
99 uint64_t * maxiocount_result
)
101 struct kern_direct_file_io_ref_t
* ref
;
104 struct vnode_attr va
;
110 off_t maxiocount
, count
;
112 int (*do_ioctl
)(void * p1
, void * p2
, int theIoctl
, caddr_t result
);
118 ref
= (struct kern_direct_file_io_ref_t
*) kalloc(sizeof(struct kern_direct_file_io_ref_t
));
126 p
= current_proc(); // kernproc;
127 ref
->ctx
= vfs_context_create(vfs_context_current());
129 if ((error
= vnode_open(name
, (O_CREAT
| FWRITE
), (0), 0, &ref
->vp
, ref
->ctx
)))
133 VATTR_WANTED(&va
, va_rdev
);
134 VATTR_WANTED(&va
, va_fsid
);
135 VATTR_WANTED(&va
, va_data_size
);
136 VATTR_WANTED(&va
, va_nlink
);
138 if (vnode_getattr(ref
->vp
, &va
, ref
->ctx
))
141 kprintf("vp va_rdev major %d minor %d\n", major(va
.va_rdev
), minor(va
.va_rdev
));
142 kprintf("vp va_fsid major %d minor %d\n", major(va
.va_fsid
), minor(va
.va_fsid
));
143 kprintf("vp size %qd\n", va
.va_data_size
);
145 if (ref
->vp
->v_type
== VREG
)
147 /* Don't dump files with links. */
148 if (va
.va_nlink
!= 1)
152 p1
= (void *) device
;
154 do_ioctl
= &file_ioctl
;
156 else if ((ref
->vp
->v_type
== VBLK
) || (ref
->vp
->v_type
== VCHR
))
163 do_ioctl
= &device_ioctl
;
167 /* Don't dump to non-regular files. */
172 // get partition base
174 error
= do_ioctl(p1
, p2
, DKIOCGETBASE
, (caddr_t
) partitionbase_result
);
178 // get block size & constraints
180 error
= do_ioctl(p1
, p2
, DKIOCGETBLOCKSIZE
, (caddr_t
) &blksize
);
184 maxiocount
= 1*1024*1024*1024;
186 error
= do_ioctl(p1
, p2
, DKIOCGETMAXBLOCKCOUNTREAD
, (caddr_t
) &count
);
190 if (count
&& (count
< maxiocount
))
193 error
= do_ioctl(p1
, p2
, DKIOCGETMAXBLOCKCOUNTWRITE
, (caddr_t
) &count
);
197 if (count
&& (count
< maxiocount
))
200 error
= do_ioctl(p1
, p2
, DKIOCGETMAXBYTECOUNTREAD
, (caddr_t
) &count
);
203 if (count
&& (count
< maxiocount
))
206 error
= do_ioctl(p1
, p2
, DKIOCGETMAXBYTECOUNTWRITE
, (caddr_t
) &count
);
209 if (count
&& (count
< maxiocount
))
212 error
= do_ioctl(p1
, p2
, DKIOCGETMAXSEGMENTBYTECOUNTREAD
, (caddr_t
) &count
);
215 if (count
&& (count
< maxiocount
))
218 error
= do_ioctl(p1
, p2
, DKIOCGETMAXSEGMENTBYTECOUNTWRITE
, (caddr_t
) &count
);
221 if (count
&& (count
< maxiocount
))
224 kprintf("max io 0x%qx bytes\n", maxiocount
);
225 if (maxiocount_result
)
226 *maxiocount_result
= maxiocount
;
228 // generate the block list
231 if (ref
->vp
->v_type
== VREG
)
234 while(f_offset
< (off_t
) va
.va_data_size
)
236 size_t io_size
= 1*1024*1024*1024;
239 error
= VNOP_BLOCKMAP(ref
->vp
, f_offset
, io_size
, &blkno
, (size_t *)&io_size
, NULL
, 0, NULL
);
242 callback(callback_ref
, ((uint64_t) blkno
) * blksize
, (uint64_t) io_size
);
245 callback(callback_ref
, 0ULL, 0ULL);
247 else if ((ref
->vp
->v_type
== VBLK
) || (ref
->vp
->v_type
== VCHR
))
249 error
= do_ioctl(p1
, p2
, DKIOCGETBLOCKCOUNT
, (caddr_t
) &size
);
253 callback(callback_ref
, 0ULL, size
);
254 callback(callback_ref
, size
, 0ULL);
258 *device_result
= device
;
261 kprintf("kern_open_file_for_direct_io(%d)\n", error
);
265 vnode_close(ref
->vp
, FWRITE
, ref
->ctx
);
269 vfs_context_rele(ref
->ctx
);
270 kfree(ref
, sizeof(struct kern_direct_file_io_ref_t
));
278 kern_write_file(struct kern_direct_file_io_ref_t
* ref
, off_t offset
, caddr_t addr
, vm_size_t len
)
280 return (vn_rdwr(UIO_WRITE
, ref
->vp
,
282 UIO_SYSSPACE32
, IO_SYNC
|IO_NODELOCKED
|IO_UNIT
,
283 vfs_context_ucred(ref
->ctx
), (int *) 0,
284 vfs_context_proc(ref
->ctx
)));
288 kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t
* ref
)
290 kprintf("kern_close_file_for_direct_io\n");
296 error
= vnode_close(ref
->vp
, FWRITE
, ref
->ctx
);
298 kprintf("vnode_close(%d)\n", error
);
300 vfs_context_rele(ref
->ctx
);
302 kfree(ref
, sizeof(struct kern_direct_file_io_ref_t
));