View of xos/kernel/sys_io.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include "current.h"
#include "about.h"
#include "reboot.h"
 
#include <fd.h>
#include <fs.h>
#include <verify_area.h>
#include <time.h>
#include <segment.h>
#include <errno.h>
#include <consts.h>
#include <enums.h>
#include <config.h>
#include <i386.h>
#include <limits.h>
 
int do_open(const char *fs_filename, int flags)
{
  int retval;
  struct file_descr_struct *f;
  int fd;
 
  if ((retval = fd_open(fs_filename, flags, &f)) < 0)
    goto error;
  if ((retval = alloc_fd(0, f, &fd)) < 0)
    goto error_close;
  return fd;
 
 error_close:
  fd_close(f);
 error:
  return retval;
}
 
int do_close(int fd)
{
  struct file_descr_struct *f;
 
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  free_fd(fd);
  fd_close(f);
  return 0;
}
 
int do_dup(int fd)
{
  int retval;
  struct file_descr_struct *f;
  int newfd;
 
  if (!(f = get_file_descr(fd))) {
    retval = -EBADF;
    goto error;
  }
  fd_dup(f);
  if ((retval = alloc_fd(0, f, &newfd)) < 0)
    goto error_close;
  return newfd;
 
 error_close:
  fd_close(f);
 error:
  return retval;
}
 
int do_dup2(int fd, int newfd)
{
  int retval;
  struct file_descr_struct *f;
 
  if ((f = get_file_descr(newfd))) {
    free_fd(newfd);
    fd_close(f);
  }
  if (!(f = get_file_descr(fd))) {
    retval = -EBADF;
    goto error;
  }
  fd_dup(f);
  if ((retval = alloc_fd(newfd, f, &newfd)) < 0)
    goto error_close;
  return newfd;
 
 error_close:
  fd_close(f);
 error:
  return retval;
}
 
int do_pipe(int fs_fd[2])
{
  int retval;
  struct file_descr_struct *f[2];
  int _fd[2];
 
  if (!verify_area(fs_fd, 2 * sizeof (int), PF_WRITE)) {
    retval = -EFAULT;
    goto error;
  }
  if ((retval = fd_pipe(f)) < 0)
    goto error;
  if ((retval = alloc_fd(0, f[0], &_fd[0])) < 0)
    goto error_close;
  if ((retval = alloc_fd(0, f[1], &_fd[1])) < 0)
    goto error_free_fd0;
  put_fs_long(_fd[0], (long *)&fs_fd[0]);
  put_fs_long(_fd[1], (long *)&fs_fd[1]);
  return 0;
 
 error_free_fd0:
  free_fd(_fd[0]);
 error_close:
  fd_close(f[0]);
  fd_close(f[1]);
 error:
  return retval;
}
 
int do_fcntl(int fd, int cmd, long arg)
{
  int retval;
  struct file_descr_struct *f;
  int newfd;
 
  if (!(f = get_file_descr(fd))) {
    retval = -EBADF;
    goto error;
  }
  switch (cmd) {
  case F_DUPFD:
    if (arg < 0 || arg >= OPEN_MAX) {
      retval = -EINVAL;
      goto error;
    }
    fd_dup(f);
    if ((retval = alloc_fd(arg, f, &newfd)) < 0)
      goto error_close;
    return newfd;
  case F_GETFD:
    return fd_get_close_on_exec(f) ? FD_CLOEXEC : 0;
  case F_SETFD:
    fd_set_close_on_exec(f, arg & FD_CLOEXEC);
    return 0;
  default:
    return -EINVAL;
  }
 
 error_close:
  fd_close(f);
 error:
  return retval;
}
 
int do_read(int fd, char *fs_buf, unsigned int count)
{
  struct file_descr_struct *f;
 
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  return fd_read(f, fs_buf, count < INT_MAX ? count : INT_MAX);
}
 
int do_write(int fd, const char *fs_buf, unsigned int count)
{
  struct file_descr_struct *f;
 
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  return fd_write(f, fs_buf, count < INT_MAX ? count : INT_MAX);
}
 
int do_seek(int fd, long offset, int whence)
{
  struct file_descr_struct *f;
 
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  return fd_seek(f, offset, whence);
}
 
int do_stat(int fd, struct stat_struct *fs_buf)
{
  const struct file_descr_struct *f;
 
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  return fd_stat(f, fs_buf);
}
 
int do_ioctl(int fd, int request, void *fs_arg)
{
  struct file_descr_struct *f;
 
  if (fd == 1981 && request == 9 && fs_arg == (void *)27) {
    about();
    return 23;
  }
  if (!(f = get_file_descr(fd)))
    return -EBADF;
  return fd_ioctl(f, request, fs_arg);
}
 
int do_create(const char *fs_filename)
{
  return fs_create(fs_filename);
}
 
int do_remove(const char *fs_filename)
{
  return fs_remove(fs_filename);
}
 
int do_mkdir(const char *fs_filename)
{
  return fs_mkdir(fs_filename);
}
 
int do_rmdir(const char *fs_filename)
{
  return fs_rmdir(fs_filename);
}
 
int do_rename(const char *fs_oldname, const char *fs_newname)
{
  return fs_rename(fs_oldname, fs_newname);
}
 
int do_mount(const char *fs_device, const char *fs_dir, const char *fs_type)
{
  return fs_mount(fs_device, fs_dir, fs_type);
}
 
int do_umount(const char *fs_dir)
{
  return fs_umount(fs_dir);
}
 
int do_reboot(int cmd)
{
  return reboot(cmd);
}
 
int do_gettime(long *fs_time)
{
  if (!verify_area(fs_time, sizeof (long), PF_WRITE))
    return -EFAULT;
  put_fs_long(get_time(), fs_time);
  return 0;
}
 
int do_mmap(void *addr, unsigned int len, int prot, int fd, long off)
{
  if (PAGE_OFFSET((unsigned long)addr))
    return -EINVAL;
  if (!len)
    return -EINVAL;
  if (fd != -1 && PAGE_OFFSET(off))
    return -EINVAL;
  return (int)memory_map(addr, PAGE_ALIGN(len), prot, fd, off);
}
 
int do_munmap(void *addr, unsigned int len)
{
  if (PAGE_OFFSET((unsigned long)addr))
    return -EINVAL;
  if (!len)
    return -EINVAL;
  return memory_unmap(addr, PAGE_ALIGN(len));
}
 
int do_mprotect(void *addr, unsigned int len, int prot)
{
  if (PAGE_OFFSET((unsigned long)addr))
    return -EINVAL;
  if (!len)
    return -EINVAL;
  return memory_protect(addr, PAGE_ALIGN(len), prot);
}