Fork me on GitHub

root/fs/namei.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. namei_lookup
  2. do_namei
  3. parse_namei
  4. namei

   1 /*
   2  * fiwix/fs/namei.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/sleep.h>
  10 #include <fiwix/sched.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/stat.h>
  14 #include <fiwix/mm.h>
  15 #include <fiwix/mman.h>
  16 #include <fiwix/errno.h>
  17 #include <fiwix/stdio.h>
  18 #include <fiwix/string.h>
  19 
  20 static int namei_lookup(char *name, struct inode *dir, struct inode **i_res)
  21 {
  22         if(dir->fsop && dir->fsop->lookup) {
  23                 return dir->fsop->lookup(name, dir, i_res);
  24         }
  25         return -EACCES;
  26 }
  27 
  28 static int do_namei(char *path, struct inode *dir, struct inode **i_res, struct inode **d_res, int follow_links)
  29 {
  30         char *name, *ptr_name;
  31         struct inode *i;
  32         struct superblock *sb;
  33 
  34         int errno;
  35 
  36         *i_res = dir;
  37         for(;;) {
  38                 while(*path == '/') {
  39                         path++;
  40                 }
  41                 if(*path == NULL) {
  42                         return 0;
  43                 }
  44 
  45                 /* extracts the next component of the path */
  46                 if(!(name = (char *)kmalloc())) {
  47                         return -ENOMEM;
  48                 }
  49                 ptr_name = name;
  50                 while(*path != NULL && *path != '/') {
  51                         if(ptr_name > name + NAME_MAX - 1) {
  52                                 break;
  53                         }
  54                         *ptr_name++ = *path++;
  55                 }
  56                 *ptr_name = NULL;
  57 
  58                 /*
  59                  * If the inode is the root of a file system, then return the
  60                  * inode on which the file system was mounted.
  61                  */
  62                 if(name[0] == '.' && name[1] == '.' && name[2] == NULL) {
  63                         if(dir == dir->sb->root) {
  64                                 sb = dir->sb;
  65                                 iput(dir);
  66                                 dir = sb->dir;
  67                                 dir->count++;
  68                         }
  69                 }
  70 
  71                 if((errno = check_permission(TO_EXEC, dir))) {
  72                         break;
  73                 }
  74 
  75                 dir->count++;
  76                 if((errno = namei_lookup(name, dir, &i))) {
  77                         break;
  78                 }
  79 
  80                 kfree((unsigned int)name);
  81                 if(*path == '/') {
  82                         if(!S_ISDIR(i->i_mode) && !S_ISLNK(i->i_mode)) {
  83                                 iput(dir);
  84                                 iput(i);
  85                                 return -ENOTDIR;
  86                         }
  87                         if(S_ISLNK(i->i_mode)) {
  88                                 if(i->fsop && i->fsop->followlink) {
  89                                         if((errno = i->fsop->followlink(dir, i, &i))) {
  90                                                 iput(dir);
  91                                                 return errno;
  92                                         }
  93                                 }
  94                         }
  95                 } else {
  96                         if((i->fsop && i->fsop->followlink) && follow_links) {
  97                                 if((errno = i->fsop->followlink(dir, i, &i))) {
  98                                         iput(dir);
  99                                         return errno;
 100                                 }
 101                         }
 102                 }
 103 
 104                 if(d_res) {
 105                         if(*d_res) {
 106                                 iput(*d_res);
 107                         }
 108                         *d_res = dir;
 109                 } else {
 110                         iput(dir);
 111                 }
 112                 dir = i;
 113                 *i_res = i;
 114         }
 115 
 116         kfree((unsigned int)name);
 117         if(d_res) {
 118                 if(*d_res) {
 119                         iput(*d_res);
 120                 }
 121                 /*
 122                  * If that was the last component of the path,
 123                  * then return the directory.
 124                  */
 125                 if(*path == NULL) {
 126                         *d_res = dir;
 127                         dir->count++;
 128                 } else {
 129                         /* that's an non-existent directory */
 130                         *d_res = NULL;
 131                         errno = -ENOTDIR;
 132                 }
 133                 iput(dir);
 134                 *i_res = NULL;
 135         } else {
 136                 iput(dir);
 137         }
 138 
 139         return errno;
 140 }
 141 
 142 int parse_namei(char *path, struct inode *base_dir, struct inode **i_res, struct inode **d_res, int follow_links)
 143 {
 144         struct inode *dir;
 145         int errno;
 146 
 147         if(!path) {
 148                 return -EFAULT;
 149         }
 150         if(*path == NULL) {
 151                 return -ENOENT;
 152         }
 153 
 154         if(!(dir = base_dir)) {
 155                 dir = current->pwd;
 156         }
 157 
 158         /* it is definitely an absolute path */
 159         if(path[0] == '/') {
 160                 dir = current->root;
 161         }
 162         dir->count++;
 163         errno = do_namei(path, dir, i_res, d_res, follow_links);
 164         return errno;
 165 }
 166 
 167 /*
 168  * namei() returns:
 169  * i_res -> the inode of the last component of the path, or NULL.
 170  * d_res -> the inode of the directory where i_res resides, or NULL.
 171  */
 172 int namei(char *path, struct inode **i_res, struct inode **d_res, int follow_links)
 173 {
 174         *i_res = NULL;
 175         if(d_res) {
 176                 *d_res = NULL;
 177         }
 178         return parse_namei(path, NULL, i_res, d_res, follow_links);
 179 }

/* [previous][next][first][last][top][bottom][index][help] */