~ubuntu-branches/ubuntu/trusty/ctfutils/trusty-proposed

« back to all changes in this revision

Viewing changes to sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c

  • Committer: Package Import Robot
  • Author(s): Robert Millan
  • Date: 2013-11-09 17:07:06 UTC
  • Revision ID: package-import@ubuntu.com-20131109170706-kacr6nvpkbhxsk81
Tags: upstream-9.2
ImportĀ upstreamĀ versionĀ 9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
24
 * SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include <sys/cdefs.h>
 
28
__FBSDID("$FreeBSD$");
 
29
 
 
30
#include <sys/types.h>
 
31
#include <sys/systm.h>
 
32
#include <sys/kernel.h>
 
33
#include <sys/systm.h>
 
34
#include <sys/kthread.h>
 
35
#include <sys/namei.h>
 
36
#include <sys/proc.h>
 
37
#include <sys/filedesc.h>
 
38
#include <sys/fcntl.h>
 
39
#include <sys/linker.h>
 
40
#include <sys/kobj.h>
 
41
 
 
42
void
 
43
kobj_free(void *address, size_t size)
 
44
{
 
45
 
 
46
        kmem_free(address, size);
 
47
}
 
48
 
 
49
void *
 
50
kobj_alloc(size_t size, int flag)
 
51
{
 
52
 
 
53
        return (kmem_alloc(size, (flag & KM_NOWAIT) ? KM_NOSLEEP : KM_SLEEP));
 
54
}
 
55
 
 
56
void *
 
57
kobj_zalloc(size_t size, int flag)
 
58
{
 
59
        void *p;
 
60
 
 
61
        if ((p = kobj_alloc(size, flag)) != NULL)
 
62
                bzero(p, size);
 
63
        return (p);
 
64
}
 
65
 
 
66
static void *
 
67
kobj_open_file_vnode(const char *file)
 
68
{
 
69
        struct thread *td = curthread;
 
70
        struct filedesc *fd;
 
71
        struct nameidata nd;
 
72
        int error, flags, vfslocked;
 
73
 
 
74
        fd = td->td_proc->p_fd;
 
75
        FILEDESC_XLOCK(fd);
 
76
        if (fd->fd_rdir == NULL) {
 
77
                fd->fd_rdir = rootvnode;
 
78
                vref(fd->fd_rdir);
 
79
        }
 
80
        if (fd->fd_cdir == NULL) {
 
81
                fd->fd_cdir = rootvnode;
 
82
                vref(fd->fd_cdir);
 
83
        }
 
84
        FILEDESC_XUNLOCK(fd);
 
85
 
 
86
        flags = FREAD | O_NOFOLLOW;
 
87
        NDINIT(&nd, LOOKUP, MPSAFE, UIO_SYSSPACE, file, td);
 
88
        error = vn_open_cred(&nd, &flags, 0, 0, curthread->td_ucred, NULL);
 
89
        if (error != 0)
 
90
                return (NULL);
 
91
        vfslocked = NDHASGIANT(&nd);
 
92
        NDFREE(&nd, NDF_ONLY_PNBUF);
 
93
        /* We just unlock so we hold a reference. */
 
94
        VOP_UNLOCK(nd.ni_vp, 0);
 
95
        VFS_UNLOCK_GIANT(vfslocked);
 
96
        return (nd.ni_vp);
 
97
}
 
98
 
 
99
static void *
 
100
kobj_open_file_loader(const char *file)
 
101
{
 
102
 
 
103
        return (preload_search_by_name(file));
 
104
}
 
105
 
 
106
struct _buf *
 
107
kobj_open_file(const char *file)
 
108
{
 
109
        struct _buf *out;
 
110
 
 
111
        out = kmem_alloc(sizeof(*out), KM_SLEEP);
 
112
        out->mounted = root_mounted();
 
113
        /*
 
114
         * If root is already mounted we read file using file system,
 
115
         * if not, we use loader.
 
116
         */
 
117
        if (out->mounted)
 
118
                out->ptr = kobj_open_file_vnode(file);
 
119
        else
 
120
                out->ptr = kobj_open_file_loader(file);
 
121
        if (out->ptr == NULL) {
 
122
                kmem_free(out, sizeof(*out));
 
123
                return ((struct _buf *)-1);
 
124
        }
 
125
        return (out);
 
126
}
 
127
 
 
128
static int
 
129
kobj_get_filesize_vnode(struct _buf *file, uint64_t *size)
 
130
{
 
131
        struct vnode *vp = file->ptr;
 
132
        struct vattr va;
 
133
        int error, vfslocked;
 
134
 
 
135
        vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 
136
        vn_lock(vp, LK_SHARED | LK_RETRY);
 
137
        error = VOP_GETATTR(vp, &va, curthread->td_ucred);
 
138
        VOP_UNLOCK(vp, 0);
 
139
        if (error == 0)
 
140
                *size = (uint64_t)va.va_size;
 
141
        VFS_UNLOCK_GIANT(vfslocked);
 
142
        return (error);
 
143
}
 
144
 
 
145
static int
 
146
kobj_get_filesize_loader(struct _buf *file, uint64_t *size)
 
147
{
 
148
        void *ptr;
 
149
 
 
150
        ptr = preload_search_info(file->ptr, MODINFO_SIZE);
 
151
        if (ptr == NULL)
 
152
                return (ENOENT);
 
153
        *size = (uint64_t)*(size_t *)ptr;
 
154
        return (0);
 
155
}
 
156
 
 
157
int
 
158
kobj_get_filesize(struct _buf *file, uint64_t *size)
 
159
{
 
160
 
 
161
        if (file->mounted)
 
162
                return (kobj_get_filesize_vnode(file, size));
 
163
        else
 
164
                return (kobj_get_filesize_loader(file, size));
 
165
}
 
166
 
 
167
int
 
168
kobj_read_file_vnode(struct _buf *file, char *buf, unsigned size, unsigned off)
 
169
{
 
170
        struct vnode *vp = file->ptr;
 
171
        struct thread *td = curthread;
 
172
        struct uio auio;
 
173
        struct iovec aiov;
 
174
        int error, vfslocked;
 
175
 
 
176
        bzero(&aiov, sizeof(aiov));
 
177
        bzero(&auio, sizeof(auio));
 
178
 
 
179
        aiov.iov_base = buf;
 
180
        aiov.iov_len = size;
 
181
 
 
182
        auio.uio_iov = &aiov;
 
183
        auio.uio_offset = (off_t)off;
 
184
        auio.uio_segflg = UIO_SYSSPACE;
 
185
        auio.uio_rw = UIO_READ;
 
186
        auio.uio_iovcnt = 1;
 
187
        auio.uio_resid = size;
 
188
        auio.uio_td = td;
 
189
 
 
190
        vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 
191
        vn_lock(vp, LK_SHARED | LK_RETRY);
 
192
        error = VOP_READ(vp, &auio, IO_UNIT | IO_SYNC, td->td_ucred);
 
193
        VOP_UNLOCK(vp, 0);
 
194
        VFS_UNLOCK_GIANT(vfslocked);
 
195
        return (error != 0 ? -1 : size - auio.uio_resid);
 
196
}
 
197
 
 
198
int
 
199
kobj_read_file_loader(struct _buf *file, char *buf, unsigned size, unsigned off)
 
200
{
 
201
        char *ptr;
 
202
 
 
203
        ptr = preload_fetch_addr(file->ptr);
 
204
        if (ptr == NULL)
 
205
                return (ENOENT);
 
206
        bcopy(ptr + off, buf, size);
 
207
        return (0);
 
208
}
 
209
 
 
210
int
 
211
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
 
212
{
 
213
 
 
214
        if (file->mounted)
 
215
                return (kobj_read_file_vnode(file, buf, size, off));
 
216
        else
 
217
                return (kobj_read_file_loader(file, buf, size, off));
 
218
}
 
219
 
 
220
void
 
221
kobj_close_file(struct _buf *file)
 
222
{
 
223
 
 
224
        if (file->mounted) {
 
225
                struct vnode *vp = file->ptr;
 
226
                struct thread *td = curthread;
 
227
                int vfslocked;
 
228
 
 
229
                vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 
230
                vn_close(vp, FREAD, td->td_ucred, td);
 
231
                VFS_UNLOCK_GIANT(vfslocked);
 
232
        }
 
233
        kmem_free(file, sizeof(*file));
 
234
}