📄 fs.c
字号:
/** * fs.c - A set of APIs that used to handle files and devices. * * Copyright (C) 2008 ZhangHu * All rights reserved. * E-MAIL: anmnmnly@gmail.com * * 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 "include/types.h"#include "include/irq.h"#include "include/list.h"#include "include/mem.h"#include "fs/fs.h"#include "drivers/chdev.h"#include "common/string.h"static uword_t file_fd = 0;/** * add_fd_node_to_current_task: Add a file node to current task. * @list: Pointer to the file node. * @return: * * @notes: */static void add_fd_node_to_current_task(slist_t *list){ if(list == NULL) { return; } mac_disable_irq(); add_node_single_list_head(&(current()->fd_node), list); mac_enable_irq();}/** * find_file_node_from_current_task: find a file node according to 'fd'. * @fd: file descriptor. * @return: file_node Pointer. * * @notes: */static file_node *get_file_node_from_current_task(word_t fd) { slist_t *slist; file_node *fn; slist = (current())->fd_node.next; while(slist != NULL) { fn = mac_find_entry(slist, file_node, link); if(fn->fd == fd) { break; } else { slist = slist->next; } } if(slist == NULL) { return NULL; } return fn;}/** * delete_file_node_from_current_task: delete a file node from current task. * @fd: file descriptor. * @return: TRUE if successful, otherwise FALSE. * * @notes: */static void delete_file_node_from_current_task(file_node *fn) { if(fn == NULL) { return; } mac_disable_irq(); del_node_single_list(&(current()->fd_node), &fn->link); mac_enable_irq(); kfree(fn);}/** * get_fd_number - Get a file descriptor. * @return: return a free file descriptor. * * @notes: */static uword_t get_fd_number(void) { mac_disable_irq(); if(file_fd++ >= (~0)) { file_fd = 0; } mac_enable_irq(); return file_fd;}/** * open - It opens a device. * @path: Pointer to a string that describes the name of a device. * @return: File descriptor. * * @notes: */word_t open(const char_t *path) { device_t *dev = NULL; chdev_t *pchdev = NULL; file_node *fn = NULL; dev = device_open(path); if(dev == NULL) { return -1; } if((fn = (file_node*)kmalloc(sizeof(file_node))) == NULL) { return -1; } kmemset(fn, 0, sizeof(file_node)); fn->fd = get_fd_number(); fn->device = dev; add_fd_node_to_current_task(&fn->link); if(dev->dev_type == CHDEV) { pchdev = (chdev_t*)dev; if((pchdev->op != NULL) && (pchdev->op->open != NULL)) { spin_lock(&fn->device->lock); pchdev->op->open(); spin_unlock(&fn->device->lock); } } return fn->fd;}/** * write - It writes data to a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @buf: Pointer to a data buffer. * @nbytes: The length of data buffer. * @return: The number of wrote data. * * @notes: */uword_t write(word_t fd, const char_t *buf, uword_t nbytes) { file_node *fn = NULL; chdev_t *pchdev = NULL; int result = 0; fn = get_file_node_from_current_task(fd); if(fn == NULL) { return result; } if(fn->device->dev_type == CHDEV) { pchdev = (chdev_t*)fn->device; if((pchdev->op != NULL) && (pchdev->op->write != NULL)) { spin_lock(&fn->device->lock); result = pchdev->op->write(buf, nbytes, ((chdev_t*)fn->device)->loff); spin_unlock(&fn->device->lock); } } return result;}/** * write - It reads data from a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @buf: Pointer to a data buffer. * @nbytes: The length of data buffer. * @return: The number of read data. * * @notes: */uword_t read(word_t fd, char_t *buf, uword_t nbytes) { file_node *fn = NULL; chdev_t *pchdev = NULL; word_t result = 0; fn = get_file_node_from_current_task(fd); if(fn == NULL) { return result; } if(fn->device->dev_type == CHDEV) { pchdev = (chdev_t*)fn->device; if((pchdev->op != NULL) && (pchdev->op->read != NULL)) { spin_lock(&fn->device->lock); result = pchdev->op->read(buf, nbytes, ((chdev_t*)fn->device)->loff); spin_unlock(&fn->device->lock); } } return result;}/** * llseek - It modifies write-read offset. * @fd: A file descriptor returned by 'open()'. * @loff: New write-read offset. * @return: The new write-read offset. * * @notes: */loff_t llseek(word_t fd, loff_t loff) { file_node *fn = NULL; chdev_t *pchdev = NULL; fn = get_file_node_from_current_task(fd); if(fn == NULL) { return -1; } if(fn->device->dev_type == CHDEV) { pchdev = (chdev_t*)fn->device; spin_lock(&fn->device->lock); pchdev->loff = loff; spin_unlock(&fn->device->lock); } return loff;}/** * ioctl - It modifies properties of a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @cmd: Command cord. * @arg: Pointer to parameters of command. * @return: TRUE if successful, otherwise FALSE. * * @notes: ioctcl dosen't explain or execute any command. It only transfer * command and it's parameters to device driver. */word_t ioctl(word_t fd, uword_t cmd, void *arg) { file_node *fn = NULL; chdev_t *pchdev = NULL; fn = get_file_node_from_current_task(fd); if(fn == NULL) { return FALSE; } if(fn->device->dev_type == CHDEV) { pchdev = (chdev_t*)fn->device; if((pchdev->op != NULL) && (pchdev->op->ioctl != NULL)) { spin_lock(&fn->device->lock); pchdev->op->ioctl(cmd, arg); spin_unlock(&fn->device->lock); return TRUE; } } return FALSE;}/** * close - It closes a device opened by 'open()'. * @fd: A file descriptor returned by 'open()'. * @return: TRUE if successful, otherwise FALSE. * * @notes: */word_t close(word_t fd) { file_node *fn = NULL; chdev_t *pchdev = NULL; fn = get_file_node_from_current_task(fd); if(fn == NULL) { return FALSE; } if(fn->device->dev_type == CHDEV) { pchdev = (chdev_t*)fn->device; if((pchdev->op != NULL) && (pchdev->op->close != NULL)) { spin_lock(&fn->device->lock); pchdev->op->close(); device_close(fn->device); spin_unlock(&fn->device->lock); } } delete_file_node_from_current_task(fn); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -