Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (6.39 KB)

1
/*-
2
 * Copyright (c) 2007, Kohsuke Ohtani All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 * 3. Neither the name of the author nor the names of any co-contributors
13
 *    may be used to endorse or promote products derived from this software
14
 *    without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28

    
29
/*
30
 * vfs_task.c - Routines to manage the per task data.
31
 */
32

    
33
#include <sys/prex.h>
34
#include <sys/list.h>
35

    
36
#include <limits.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <stdio.h>
40
#include <errno.h>
41

    
42
#include "vfs.h"
43

    
44
#define TASK_MAXBUCKETS        32                /* number of task hash buckets */
45

    
46
#define TASKHASH(x)        (int)((x) & (TASK_MAXBUCKETS - 1))
47

    
48
/*
49
 * Hash table for task.
50
 */
51
static struct list task_table[TASK_MAXBUCKETS];
52

    
53
/*
54
 * Global lock for task access.
55
 */
56
#if CONFIG_FS_THREADS > 1
57
static mutex_t task_lock = MUTEX_INITIALIZER;
58
#define TASK_LOCK()        mutex_lock(&task_lock)
59
#define TASK_UNLOCK()        mutex_unlock(&task_lock)
60
#else
61
#define TASK_LOCK()
62
#define TASK_UNLOCK()
63
#endif
64

    
65
/*
66
 * Convert task ID to a task structure.
67
 * Returns locked task. Caller must unlock it after using it.
68
 */
69
struct task *
70
task_lookup(task_t task)
71
{
72
        list_t head, n;
73
        struct task *t;
74

    
75
        if (task == TASK_NULL)
76
                return NULL;
77

    
78
        TASK_LOCK();
79
        head = &task_table[TASKHASH(task)];
80
        for (n = list_first(head); n != head; n = list_next(n)) {
81
                t = list_entry(n, struct task, t_link);
82
                ASSERT(t->t_taskid);
83
                if (t->t_taskid == task) {
84
                        TASK_UNLOCK();
85
                        mutex_lock(&t->t_lock);
86
                        return t;
87
                }
88
        }
89
        TASK_UNLOCK();
90

    
91
        /* Not found */
92
        return NULL;
93
}
94

    
95
/*
96
 * Allocate new task.
97
 */
98
int
99
task_alloc(task_t task, struct task **pt)
100
{
101
        struct task *t;
102

    
103
        /* Check if specified task already exists. */
104
        if (task_lookup(task) != NULL)
105
                return EINVAL;
106

    
107
        if (!(t = malloc(sizeof(struct task))))
108
                return ENOMEM;
109
        memset(t, 0, sizeof(struct task));
110
        t->t_taskid = task;
111
        strlcpy(t->t_cwd, "/", sizeof(t->t_cwd));
112
        mutex_init(&t->t_lock);
113

    
114
        TASK_LOCK();
115
        list_insert(&task_table[TASKHASH(task)], &t->t_link);
116
        TASK_UNLOCK();
117
        *pt = t;
118
        return 0;
119
}
120

    
121
/*
122
 * Free task and related resource.
123
 */
124
void
125
task_free(struct task *t)
126
{
127

    
128
        TASK_LOCK();
129
        list_remove(&t->t_link);
130
        mutex_unlock(&t->t_lock);
131
        mutex_destroy(&t->t_lock);
132
        free(t);
133
        TASK_UNLOCK();
134
}
135

    
136
/*
137
 * Set task id of the specified task.
138
 */
139
void
140
task_setid(struct task *t, task_t task)
141
{
142

    
143
        TASK_LOCK();
144
        list_remove(&t->t_link);
145
        t->t_taskid = task;
146
        list_insert(&task_table[TASKHASH(task)], &t->t_link);
147
        TASK_UNLOCK();
148
}
149

    
150
/*
151
 * Unlock task.
152
 */
153
void
154
task_unlock(struct task *t)
155
{
156

    
157
        mutex_unlock(&t->t_lock);
158
}
159

    
160
/*
161
 * Convert a file descriptor into a pointer
162
 * to a file structre.
163
 */
164
file_t
165
task_getfp(struct task *t, int fd)
166
{
167

    
168
        if (fd < 0 || fd >= OPEN_MAX)
169
                return NULL;
170

    
171
        return t->t_ofile[fd];
172
}
173

    
174
/*
175
 * Set file pointer for task/fd pair.
176
 */
177
void
178
task_setfp(struct task *t, int fd, file_t fp)
179
{
180

    
181
        t->t_ofile[fd] = fp;
182
}
183

    
184
/*
185
 * Get new file descriptor in the task.
186
 * Returns -1 if there is no empty slot.
187
 */
188
int
189
task_newfd(struct task *t)
190
{
191
        int fd;
192

    
193
        /*
194
         * Find the smallest empty slot in the fd array.
195
         */
196
        for (fd = 0; fd < OPEN_MAX; fd++) {
197
                if (t->t_ofile[fd] == NULL)
198
                        break;
199
        }
200
        if (fd == OPEN_MAX)
201
                return -1;        /* slot full */
202

    
203
        return fd;
204
}
205

    
206
/*
207
 * Delete a file descriptor.
208
 */
209
void
210
task_delfd(struct task *t, int fd)
211
{
212

    
213
        t->t_ofile[fd] = NULL;
214
}
215

    
216
/*
217
 * Convert to full path from the cwd of task and path.
218
 * @t:    task structure
219
 * @path: target path
220
 * @full: full path to be returned
221
 * @acc: access mode
222
 */
223
int
224
task_conv(struct task *t, char *path, int acc, char *full)
225
{
226
        char *src, *tgt, *p, *end, *cwd;
227
        size_t len = 0;
228

    
229
        cwd = t->t_cwd;
230
        path[PATH_MAX - 1] = '\0';
231
        len = strlen(path);
232
        if (len >= PATH_MAX)
233
                return ENAMETOOLONG;
234
        if (strlen(cwd) + len >= PATH_MAX)
235
                return ENAMETOOLONG;
236
        src = path;
237
        tgt = full;
238
        end = src + len;
239
        if (path[0] == '/') {
240
                *tgt++ = *src++;
241
                len++;
242
        } else {
243
                strlcpy(full, cwd, PATH_MAX);
244
                len = strlen(cwd);
245
                tgt += len;
246
                if (len > 1 && path[0] != '.') {
247
                        *tgt = '/';
248
                        tgt++;
249
                        len++;
250
                }
251
        }
252
        while (*src) {
253
                p = src;
254
                while (*p != '/' && *p != '\0')
255
                        p++;
256
                *p = '\0';
257
                if (!strcmp(src, "..")) {
258
                        if (len >= 2) {
259
                                len -= 2;
260
                                tgt -= 2;        /* skip previous '/' */
261
                                while (*tgt != '/') {
262
                                        tgt--;
263
                                        len--;
264
                                }
265
                                if (len == 0) {
266
                                        tgt++;
267
                                        len++;
268
                                }
269
                        }
270
                } else if (!strcmp(src, ".")) {
271
                        /* Ignore "." */
272
                } else {
273
                        while (*src != '\0') {
274
                                *tgt++ = *src++;
275
                                len++;
276
                        }
277
                }
278
                if (p == end)
279
                        break;
280
                if (len > 0 && *(tgt - 1) != '/') {
281
                        *tgt++ = '/';
282
                        len++;
283
                }
284
                src = p + 1;
285
        }
286
        *tgt = '\0';
287

    
288
        /* Check if the client task has required permission */
289
        return sec_file_permission(t->t_taskid, full, acc);
290
}
291

    
292
#ifdef DEBUG_VFS
293
void
294
task_dump(void)
295
{
296
        list_t head, n;
297
        struct task *t;
298
        int i;
299

    
300
        TASK_LOCK();
301
        dprintf("Dump file data\n");
302
        dprintf(" task     opens   cwd\n");
303
        dprintf(" -------- ------- ------------------------------\n");
304
        for (i = 0; i < TASK_MAXBUCKETS; i++) {
305
                head = &task_table[i];
306
                for (n = list_first(head); n != head; n = list_next(n)) {
307
                        t = list_entry(n, struct task, t_link);
308
                        dprintf(" %08x %7x %s\n", (int)t->t_taskid, t->t_nopens,
309
                               t->t_cwd);
310
                }
311
        }
312
        dprintf("\n");
313
        TASK_UNLOCK();
314
}
315
#endif
316

    
317
void
318
task_init(void)
319
{
320
        int i;
321

    
322
        for (i = 0; i < TASK_MAXBUCKETS; i++)
323
                list_init(&task_table[i]);
324
}