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(!i) {
  64                         /*
  65                          * If the file does not exist, you need enough
  66                          * permission in the directory to create it.
  67                          */
  68                         if(check_permission(TO_EXEC | TO_WRITE, dir) < 0) {
  69                                 iput(i);
  70                                 iput(dir);
  71                                 free_name(tmp_name);
  72                                 return -EACCES;
  73                         }
  74                 }
  75                 if(errno) {     /* assumes -ENOENT */
  76                         if(dir->fsop && dir->fsop->create) {
  77                                 errno = dir->fsop->create(dir, basename, mode, &i);
  78                                 if(errno) {
  79                                         iput(dir);
  80                                         free_name(tmp_name);
  81                                         return errno;
  82                                 }
  83                         } else {
  84                                 iput(dir);
  85                                 free_name(tmp_name);
  86                                 return -EACCES;
  87                         }
  88                 }
  89         } else {
  90                 if(errno) {
  91                         iput(dir);
  92                         free_name(tmp_name);
  93                         return errno;
  94                 }
  95                 if(S_ISDIR(i->i_mode) && (flags & (O_RDWR | O_WRONLY | O_TRUNC))) {
  96                         iput(i);
  97                         iput(dir);
  98                         free_name(tmp_name);
  99                         return -EISDIR;
 100                 }
 101                 mode = 0;
 102         }
 103 
 104         if((flags & O_ACCMODE) == O_RDONLY) {
 105                 perms = TO_READ;
 106         } else if((flags & O_ACCMODE) == O_WRONLY) {
 107                 perms = TO_WRITE;
 108         } else {
 109                 perms = TO_READ | TO_WRITE;
 110         }
 111         if((errno = check_permission(perms, i))) {
 112                 iput(i);
 113                 iput(dir);
 114                 free_name(tmp_name);
 115                 return errno;
 116         }
 117         if((fd = get_new_fd(i)) < 0) {
 118                 iput(i);
 119                 iput(dir);
 120                 free_name(tmp_name);
 121                 return fd;
 122         }
 123         if((ufd = get_new_user_fd(0)) < 0) {
 124                 release_fd(fd);
 125                 iput(i);
 126                 iput(dir);
 127                 free_name(tmp_name);
 128                 return ufd;
 129         }
 130 
 131 #ifdef __DEBUG__
 132         printk("\t(ufd = %d)\n", ufd);
 133 #endif /*__DEBUG__ */
 134 
 135         fd_table[fd].flags = flags;
 136         current->fd[ufd] = fd;
 137         if(i->fsop && i->fsop->open) {
 138                 if((errno = i->fsop->open(i, &fd_table[fd])) < 0) {
 139                         release_fd(fd);
 140                         release_user_fd(ufd);
 141                         iput(i);
 142                         iput(dir);
 143                         free_name(tmp_name);
 144                         return errno;
 145                 }
 146                 iput(dir);
 147                 free_name(tmp_name);
 148                 return ufd;
 149         }
 150 
 151         printk("WARNING: %s(): file '%s' (inode %d) without the open() method!\n", __FUNCTION__, tmp_name, i->inode);
 152         release_fd(fd);
 153         release_user_fd(ufd);
 154         iput(i);
 155         iput(dir);
 156         free_name(tmp_name);
 157         return -EINVAL;
 158 }

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