Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/fs/vfs/vfs_task.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. task_lookup
  2. task_alloc
  3. task_free
  4. task_setid
  5. task_unlock
  6. task_getfp
  7. task_setfp
  8. task_newfd
  9. task_delfd
  10. task_conv
  11. task_dump
  12. task_init

   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] */