Statistics
| Branch: | Revision:

root / prex-0.9.0 / usr / server / fs / vfs / vfs_lookup.c @ 03e9c04a

History | View | Annotate | Download (4.34 KB)

1
/*
2
 * Copyright (c) 2005-2007, Kohsuke Ohtani
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
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

    
30
/*
31
 * vfs_lookup.c - vnode lookup function.
32
 */
33

    
34
#include <sys/vnode.h>
35
#include <sys/mount.h>
36

    
37
#include <limits.h>
38
#include <unistd.h>
39
#include <string.h>
40
#include <errno.h>
41

    
42
#include "vfs.h"
43

    
44
/*
45
 * Convert a pathname into a pointer to a locked vnode.
46
 *
47
 * @path: full path name.
48
 * @vpp:  vnode to be returned.
49
 */
50
int
51
namei(char *path, vnode_t *vpp)
52
{
53
        char *p;
54
        char node[PATH_MAX];
55
        char name[PATH_MAX];
56
        mount_t mp;
57
        vnode_t dvp, vp;
58
        int error, i;
59

    
60
        DPRINTF(VFSDB_VNODE, ("namei: path=%s\n", path));
61

    
62
        /*
63
         * Convert a full path name to its mount point and
64
         * the local node in the file system.
65
         */
66
        if (vfs_findroot(path, &mp, &p))
67
                return ENOTDIR;
68
        strlcpy(node, "/", sizeof(node));
69
        strlcat(node, p, sizeof(node));
70
        vp = vn_lookup(mp, node);
71
        if (vp) {
72
                /* vnode is already active. */
73
                *vpp = vp;
74
                return 0;
75
        }
76
        /*
77
         * Find target vnode, started from root directory.
78
         * This is done to attach the fs specific data to
79
         * the target vnode.
80
         */
81
        if ((dvp = mp->m_root) == NULL)
82
                sys_panic("VFS: no root");
83

    
84
        vref(dvp);
85
        vn_lock(dvp);
86
        node[0] = '\0';
87

    
88
        while (*p != '\0') {
89
                /*
90
                 * Get lower directory/file name.
91
                 */
92
                while (*p == '/')
93
                        p++;
94
                for (i = 0; i < PATH_MAX; i++) {
95
                        if (*p == '\0' || *p == '/')
96
                                break;
97
                        name[i] = *p++;
98
                }
99
                name[i] = '\0';
100

    
101
                /*
102
                 * Get a vnode for the target.
103
                 */
104
                strlcat(node, "/", sizeof(node));
105
                strlcat(node, name, sizeof(node));
106
                vp = vn_lookup(mp, node);
107
                if (vp == NULL) {
108
                        vp = vget(mp, node);
109
                        if (vp == NULL) {
110
                                vput(dvp);
111
                                return ENOMEM;
112
                        }
113
                        /* Find a vnode in this directory. */
114
                        error = VOP_LOOKUP(dvp, name, vp);
115
                        if (error || (*p == '/' && vp->v_type != VDIR)) {
116
                                /* Not found */
117
                                vput(vp);
118
                                vput(dvp);
119
                                return error;
120
                        }
121
                }
122
                vput(dvp);
123
                dvp = vp;
124
                while (*p != '\0' && *p != '/')
125
                        p++;
126
        }
127

    
128
        /*
129
         * Detemine X permission.
130
         */
131
        if (vp->v_type != VDIR && sec_vnode_permission(path) != 0) {
132
                vp->v_mode &= ~(0111);
133
        }
134

    
135
        *vpp = vp;
136
        return 0;
137
}
138

    
139
/*
140
 * Search a pathname.
141
 * This is a very central but not so complicated routine. ;-P
142
 *
143
 * @path: full path.
144
 * @vpp:  pointer to locked vnode for directory.
145
 * @name: pointer to file name in path.
146
 *
147
 * This routine returns a locked directory vnode and file name.
148
 */
149
int
150
lookup(char *path, vnode_t *vpp, char **name)
151
{
152
        char buf[PATH_MAX];
153
        char root[] = "/";
154
        char *file, *dir;
155
        vnode_t vp;
156
        int error;
157

    
158
        DPRINTF(VFSDB_VNODE, ("lookup: path=%s\n", path));
159

    
160
        /*
161
         * Get the path for directory.
162
         */
163
        strlcpy(buf, path, sizeof(buf));
164
        file = strrchr(buf, '/');
165
        if (!buf[0])
166
                return ENOTDIR;
167
        if (file == buf)
168
                dir = root;
169
        else {
170
                *file = '\0';
171
                dir = buf;
172
        }
173
        /*
174
         * Get the vnode for directory
175
         */
176
        if ((error = namei(dir, &vp)) != 0)
177
                return error;
178
        if (vp->v_type != VDIR) {
179
                vput(vp);
180
                return ENOTDIR;
181
        }
182
        *vpp = vp;
183

    
184
        /*
185
         * Get the file name
186
         */
187
        *name = strrchr(path, '/') + 1;
188
        return 0;
189
}