|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/fs/vfs/vfs_task.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
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 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |