Fork me on GitHub

root/kernel/syscalls/open.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_open

   1 /*
   2  * fiwix/kernel/syscalls/open.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/syscalls.h>
   9 #include <fiwix/stat.h>
  10 #include <fiwix/types.h>
  11 #include <fiwix/fcntl.h>
  12 #include <fiwix/errno.h>
  13 #include <fiwix/stdio.h>
  14 #include <fiwix/string.h>
  15 
  16 int sys_open(const char *filename, int flags, __mode_t mode)
  17 {
  18         int fd, ufd;
  19         struct inode *i, *dir;
  20         char *tmp_name, *basename;
  21         int errno, follow_links, perms;
  22 
  23 #ifdef __DEBUG__
  24         printk("(pid %d) sys_open('%s', %o, %o)\n", current->pid, filename, flags, mode);
  25 #endif /*__DEBUG__ */
  26 
  27         if((errno = malloc_name(filename, &tmp_name)) < 0) {
  28                 return errno;
  29         }
  30 
  31         basename = get_basename(tmp_name);
  32         follow_links = (flags & O_NOFOLLOW) ? !FOLLOW_LINKS : FOLLOW_LINKS;
  33         if((errno = namei(tmp_name, &i, &dir, follow_links))) {
  34                 if(!dir) {
  35                         free_name(tmp_name);
  36                         if(flags & O_CREAT) {
  37                                 return -ENOENT;
  38                         }
  39                         return errno;
  40                 }
  41         }
  42 
  43 #ifdef __DEBUG__
  44         printk("\t(inode = %d)\n", i ? i->inode : -1);
  45 #endif /*__DEBUG__ */
  46 
  47         if(!errno) {
  48                 if(S_ISLNK(i->i_mode) && (flags & O_NOFOLLOW)) {
  49                         iput(i);
  50                         iput(dir);
  51                         free_name(tmp_name);
  52                         return -ELOOP;
  53                 }
  54         }
  55 
  56         if(flags & O_CREAT) {
  57                 if(!errno && (flags & O_EXCL)) {
  58                         iput(i);
  59                         iput(dir);
  60                         free_name(tmp_name);
  61                         return -EEXIST;
  62                 }
  63                 if(check_permission(TO_EXEC | TO_WRITE, dir) < 0) {
  64                         iput(i);
  65                         iput(dir);
  66                         free_name(tmp_name);
  67                         return -EACCES;
  68                 }
  69                 if(errno) {     /* assumes -ENOENT */
  70                         if(dir->fsop && dir->fsop->create) {
  71                                 errno = dir->fsop->create(dir, basename, mode, &i);
  72                                 if(errno) {
  73                                         iput(dir);
  74                                         free_name(tmp_name);
  75                                         return errno;
  76                                 }
  77                         } else {
  78                                 iput(dir);
  79                                 free_name(tmp_name);
  80                                 return -EACCES;
  81                         }
  82                 }
  83         } else {
  84                 if(errno) {
  85                         iput(dir);
  86                         free_name(tmp_name);
  87                         return errno;
  88                 }
  89                 if(S_ISDIR(i->i_mode) && (flags & (O_RDWR | O_WRONLY | O_TRUNC))) {
  90                         iput(i);
  91                         iput(dir);
  92                         free_name(tmp_name);
  93                         return -EISDIR;
  94                 }
  95                 mode = 0;
  96         }
  97 
  98         if((flags & O_ACCMODE) == O_RDONLY) {
  99                 perms = TO_READ;
 100         } else if((flags & O_ACCMODE) == O_WRONLY) {
 101                 perms = TO_WRITE;
 102         } else {
 103                 perms = TO_READ | TO_WRITE;
 104         }
 105         if((errno = check_permission(perms, i))) {
 106                 iput(i);
 107                 iput(dir);
 108                 free_name(tmp_name);
 109                 return errno;
 110         }
 111         if((fd = get_new_fd(i)) < 0) {
 112                 iput(i);
 113                 iput(dir);
 114                 free_name(tmp_name);
 115                 return fd;
 116         }
 117         if((ufd = get_new_user_fd(0)) < 0) {
 118                 release_fd(fd);
 119                 iput(i);
 120                 iput(dir);
 121                 free_name(tmp_name);
 122                 return ufd;
 123         }
 124 
 125 #ifdef __DEBUG__
 126         printk("\t(ufd = %d)\n", ufd);
 127 #endif /*__DEBUG__ */
 128 
 129         fd_table[fd].flags = flags;
 130         current->fd[ufd] = fd;
 131         if(i->fsop && i->fsop->open) {
 132                 if((errno = i->fsop->open(i, &fd_table[fd])) < 0) {
 133                         release_fd(fd);
 134                         release_user_fd(ufd);
 135                         iput(i);
 136                         iput(dir);
 137                         free_name(tmp_name);
 138                         return errno;
 139                 }
 140                 iput(dir);
 141                 free_name(tmp_name);
 142                 return ufd;
 143         }
 144 
 145         printk("WARNING: %s(): file '%s' (inode %d) without the open() method!\n", __FUNCTION__, tmp_name, i->inode);
 146         release_fd(fd);
 147         release_user_fd(ufd);
 148         iput(i);
 149         iput(dir);
 150         free_name(tmp_name);
 151         return -EINVAL;
 152 }

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